3 var active_feed_cat
= false;
4 var active_tab
= false;
6 var xmlhttp
= Ajax
.getTransport();
8 var init_params
= new Array();
10 var caller_subop
= false;
11 var sanity_check_done
= false;
12 var hotkey_prefix
= false;
14 function infobox_callback() {
15 if (xmlhttp
.readyState
== 4) {
16 infobox_callback2(xmlhttp
);
20 function infobox_submit_callback() {
21 if (xmlhttp
.readyState
== 4) {
22 infobox_submit_callback2(xmlhttp
);
27 function replace_pubkey_callback() {
28 if (xmlhttp
.readyState
== 4) {
30 var link
= document
.getElementById("pubGenAddress");
32 if (xmlhttp
.responseXML
) {
34 var new_link
= xmlhttp
.responseXML
.getElementsByTagName("link")[0];
37 link
.href
= new_link
.firstChild
.nodeValue
;
38 //link.innerHTML = new_link.firstChild.nodeValue;
40 new Effect
.Highlight(link
);
42 notify_info("Published feed URL changed.");
44 notify_error("Could not change feed URL.");
48 notify_error("Could not change feed URL.");
51 exception_error("replace_pubkey_callback", e
);
56 function feedlist_callback() {
57 if (xmlhttp
.readyState
== 4) {
58 return feedlist_callback2(xmlhttp
);
62 function feedlist_callback2(transport
) {
64 var container
= document
.getElementById('prefContent');
65 container
.innerHTML
=transport
.responseText
;
66 selectTab("feedConfig", true);
69 var tuple
= caller_subop
.split(":");
70 if (tuple
[0] == 'editFeed') {
71 window
.setTimeout('editFeed('+tuple
[1]+')', 100);
76 if (typeof correctPNG
!= 'undefined') {
83 exception_error("feedlist_callback2", e
);
87 /* stub for subscription dialog */
89 function dlg_frefresh_callback(transport
) {
90 return feedlist_callback2(transport
);
93 function filterlist_callback() {
94 var container
= document
.getElementById('prefContent');
95 if (xmlhttp
.readyState
== 4) {
96 container
.innerHTML
=xmlhttp
.responseText
;
97 if (typeof correctPNG
!= 'undefined') {
105 function labellist_callback2(transport
) {
109 var container
= document
.getElementById('prefContent');
111 container
.innerHTML
=transport
.responseText
;
113 if (document
.getElementById("prefLabelList")) {
114 var elems
= document
.getElementById("prefLabelList").getElementsByTagName("SPAN");
116 for (var i
= 0; i
< elems
.length
; i
++) {
117 if (elems
[i
].id
&& elems
[i
].id
.match("LILT-")) {
119 var id
= elems
[i
].id
.replace("LILT-", "");
120 new Ajax
.InPlaceEditor(elems
[i
],
121 'backend.php?op=pref-labels&subop=save&id=' + id
,
122 {cols
: 20, rows
: 1});
127 if (typeof correctPNG
!= 'undefined') {
134 exception_error("labellist_callback2", e
);
138 function feed_browser_callback() {
139 var container
= document
.getElementById('prefContent');
140 if (xmlhttp
.readyState
== 4) {
141 container
.innerHTML
=xmlhttp
.responseText
;
147 function userlist_callback() {
148 var container
= document
.getElementById('prefContent');
149 if (xmlhttp
.readyState
== 4) {
150 container
.innerHTML
=xmlhttp
.responseText
;
156 function prefslist_callback() {
157 var container
= document
.getElementById('prefContent');
158 if (xmlhttp
.readyState
== 4) {
159 container
.innerHTML
=xmlhttp
.responseText
;
165 function gethelp_callback() {
166 var container
= document
.getElementById('prefHelpBox');
167 if (xmlhttp
.readyState
== 4) {
169 container
.innerHTML
= xmlhttp
.responseText
;
170 container
.style
.display
= "block";
175 function notify_callback() {
176 if (xmlhttp
.readyState
== 4) {
177 notify_info(xmlhttp
.responseText
);
181 function prefs_reset_callback() {
182 if (xmlhttp
.readyState
== 4) {
183 notify_info(xmlhttp
.responseText
);
189 function changepass_callback() {
191 if (xmlhttp
.readyState
== 4) {
193 if (xmlhttp
.responseText
.indexOf("ERROR: ") == 0) {
194 notify_error(xmlhttp
.responseText
.replace("ERROR: ", ""));
196 notify_info(xmlhttp
.responseText
);
197 var warn
= document
.getElementById("default_pass_warning");
198 if (warn
) warn
.style
.display
= "none";
201 document
.forms
['change_pass_form'].reset();
205 exception_error("changepass_callback", e
);
209 function init_cat_inline_editor() {
212 if (document
.getElementById("prefFeedCatList")) {
213 var elems
= document
.getElementById("prefFeedCatList").getElementsByTagName("SPAN");
215 for (var i
= 0; i
< elems
.length
; i
++) {
216 if (elems
[i
].id
&& elems
[i
].id
.match("FCATT-")) {
217 var cat_id
= elems
[i
].id
.replace("FCATT-", "");
218 new Ajax
.InPlaceEditor(elems
[i
],
219 'backend.php?op=pref-feeds&subop=editCats&action=save&cid=' + cat_id
);
225 exception_error("init_cat_inline_editor", e
);
229 function infobox_feed_cat_callback2(transport
) {
231 infobox_callback2(transport
);
232 init_cat_inline_editor();
234 exception_error("infobox_feed_cat_callback2", e
);
238 function updateFeedList(sort_key
) {
240 if (!xmlhttp_ready(xmlhttp
)) {
245 var feed_search
= document
.getElementById("feed_search");
247 if (feed_search
) { search
= feed_search
.value
; }
249 var slat
= document
.getElementById("show_last_article_times");
251 var slat_checked
= false;
253 slat_checked
= slat
.checked
;
256 xmlhttp
.open("GET", "backend.php?op=pref-feeds" +
257 "&sort=" + param_escape(sort_key
) +
258 "&slat=" + param_escape(slat_checked
) +
259 "&search=" + param_escape(search
), true);
260 xmlhttp
.onreadystatechange
=feedlist_callback
;
265 function updateUsersList(sort_key
) {
267 if (!xmlhttp_ready(xmlhttp
)) {
272 var user_search
= document
.getElementById("user_search");
274 if (user_search
) { search
= user_search
.value
; }
276 xmlhttp
.open("GET", "backend.php?op=pref-users&sort="
277 + param_escape(sort_key
) +
278 "&search=" + param_escape(search
), true);
279 xmlhttp
.onreadystatechange
=userlist_callback
;
284 function addLabel() {
288 var caption
= prompt(__("Please enter label caption:"), "");
290 if (caption
== null) {
295 alert(__("Can't create label: missing caption."));
299 // we can be called from some other tab
300 active_tab
= "labelConfig";
302 query
= "backend.php?op=pref-labels&subop=add&caption=" +
303 param_escape(caption
);
305 new Ajax
.Request(query
, {
306 onComplete: function(transport
) {
307 infobox_submit_callback2(transport
);
311 exception_error("addLabel", e
);
319 var link
= document
.getElementById("fadd_link");
321 if (link
.value
.length
== 0) {
322 alert(__("Error: No feed URL given."));
323 } else if (!isValidURL(link
.value
)) {
324 alert(__("Error: Invalid feed URL."));
326 notify_progress("Adding feed...");
328 var query
= "backend.php?op=pref-feeds&subop=add&from=tt-rss&feed_url=" +
329 param_escape(link
.value
);
331 new Ajax
.Request(query
, {
332 onComplete: function(transport
) {
333 feedlist_callback2(transport
);
341 exception_error("addFeed", e
);
346 function addFeedCat() {
348 if (!xmlhttp_ready(xmlhttp
)) {
353 var cat
= document
.getElementById("fadd_cat");
355 if (cat
.value
.length
== 0) {
356 alert(__("Can't add category: no name specified."));
358 notify_progress("Adding feed category...");
360 var query
= "backend.php?op=pref-feeds&subop=editCats&action=add&cat=" +
361 param_escape(cat
.value
);
363 new Ajax
.Request(query
, {
364 onComplete: function(transport
) {
365 infobox_feed_cat_callback2(transport
);
375 if (!xmlhttp_ready(xmlhttp
)) {
380 var sqlexp
= document
.getElementById("uadd_box");
382 if (sqlexp
.value
.length
== 0) {
383 alert(__("Can't add user: no login specified."));
385 notify_progress("Adding user...");
387 xmlhttp
.open("GET", "backend.php?op=pref-users&subop=add&login=" +
388 param_escape(sqlexp
.value
), true);
390 xmlhttp
.onreadystatechange
=userlist_callback
;
398 function editUser(id
) {
404 notify_progress("Loading, please wait...");
406 selectTableRowsByIdPrefix('prefUserList', 'UMRR-', 'UMCHK-', false);
407 selectTableRowById('UMRR-'+id
, 'UMCHK-'+id
, true);
409 disableContainerChildren("userOpToolbar", false);
411 var query
= "backend.php?op=pref-users&subop=edit&id=" +
414 new Ajax
.Request(query
, {
415 onComplete: function(transport
) {
416 infobox_callback2(transport
);
420 exception_error("editUser", e
);
425 function editFilter(id
) {
431 notify_progress("Loading, please wait...");
433 disableContainerChildren("filterOpToolbar", false);
435 selectTableRowsByIdPrefix('prefFilterList', 'FILRR-', 'FICHK-', false);
436 selectTableRowById('FILRR-'+id
, 'FICHK-'+id
, true);
438 var query
= "backend.php?op=pref-filters&subop=edit&id=" +
441 new Ajax
.Request(query
, {
442 onComplete: function(transport
) {
443 infobox_callback2(transport
);
446 exception_error("editFilter", e
);
450 function editFeed(feed
) {
456 notify_progress("Loading, please wait...");
458 // clean selection from all rows & select row being edited
459 selectTableRowsByIdPrefix('prefFeedList', 'FEEDR-', 'FRCHK-', false);
460 selectTableRowById('FEEDR-'+feed
, 'FRCHK-'+feed
, true);
462 disableContainerChildren("feedOpToolbar", false);
464 var query
= "backend.php?op=pref-feeds&subop=editfeed&id=" +
467 new Ajax
.Request(query
, {
468 onComplete: function(transport
) {
469 infobox_callback2(transport
);
473 exception_error("editFeed", e
);
477 function getSelectedLabels() {
478 return getSelectedTableRowIds("prefLabelList", "LILRR");
481 function getSelectedUsers() {
482 return getSelectedTableRowIds("prefUserList", "UMRR");
485 function getSelectedFeeds() {
486 return getSelectedTableRowIds("prefFeedList", "FEEDR");
489 function getSelectedFilters() {
490 return getSelectedTableRowIds("prefFilterList", "FILRR");
493 function getSelectedFeedCats() {
494 return getSelectedTableRowIds("prefFeedCatList", "FCATR");
498 function removeSelectedLabels() {
500 var sel_rows
= getSelectedLabels();
502 if (sel_rows
.length
> 0) {
504 var ok
= confirm(__("Remove selected labels?"));
507 notify_progress("Removing selected labels...");
509 var query
= "backend.php?op=pref-labels&subop=remove&ids="+
510 param_escape(sel_rows
.toString());
512 new Ajax
.Request(query
, {
513 onComplete: function(transport
) {
514 labellist_callback2(transport
);
519 alert(__("No labels are selected."));
525 function removeSelectedUsers() {
527 if (!xmlhttp_ready(xmlhttp
)) {
532 var sel_rows
= getSelectedUsers();
534 if (sel_rows
.length
> 0) {
536 var ok
= confirm(__("Remove selected users?"));
539 notify_progress("Removing selected users...");
541 xmlhttp
.open("GET", "backend.php?op=pref-users&subop=remove&ids="+
542 param_escape(sel_rows
.toString()), true);
543 xmlhttp
.onreadystatechange
=userlist_callback
;
548 alert(__("No users are selected."));
554 function removeSelectedFilters() {
556 if (!xmlhttp_ready(xmlhttp
)) {
561 var sel_rows
= getSelectedFilters();
563 if (sel_rows
.length
> 0) {
565 var ok
= confirm(__("Remove selected filters?"));
568 notify_progress("Removing selected filters...");
570 xmlhttp
.open("GET", "backend.php?op=pref-filters&subop=remove&ids="+
571 param_escape(sel_rows
.toString()), true);
572 xmlhttp
.onreadystatechange
=filterlist_callback
;
576 alert(__("No filters are selected."));
583 function removeSelectedFeeds() {
587 var sel_rows
= getSelectedFeeds();
589 if (sel_rows
.length
> 0) {
591 var ok
= confirm(__("Unsubscribe from selected feeds?"));
595 notify_progress("Unsubscribing from selected feeds...");
597 var query
= "backend.php?op=pref-feeds&subop=remove&ids="+
598 param_escape(sel_rows
.toString());
600 new Ajax
.Request(query
, {
601 onComplete: function(transport
) {
602 feedlist_callback2(transport
);
607 alert(__("No feeds are selected."));
611 exception_error("removeSelectedFeeds", e
);
617 function clearSelectedFeeds() {
619 if (!xmlhttp_ready(xmlhttp
)) {
624 var sel_rows
= getSelectedFeeds();
626 if (sel_rows
.length
> 1) {
627 alert(__("Please select only one feed."));
631 if (sel_rows
.length
> 0) {
633 var ok
= confirm(__("Erase all non-starred articles in selected feed?"));
636 notify_progress("Clearing selected feed...");
637 clearFeedArticles(sel_rows
[0]);
642 alert(__("No feeds are selected."));
649 function purgeSelectedFeeds() {
651 if (!xmlhttp_ready(xmlhttp
)) {
656 var sel_rows
= getSelectedFeeds();
658 if (sel_rows
.length
> 0) {
660 var pr
= prompt(__("How many days of articles to keep (0 - use default)?"), "0");
662 if (pr
!= undefined) {
663 notify_progress("Purging selected feed...");
665 var query
= "backend.php?op=rpc&subop=purge&ids="+
666 param_escape(sel_rows
.toString()) + "&days=" + pr
;
670 new Ajax
.Request(query
, {
671 onComplete: function(transport
) {
678 alert(__("No feeds are selected."));
685 function removeSelectedFeedCats() {
687 if (!xmlhttp_ready(xmlhttp
)) {
692 var sel_rows
= getSelectedFeedCats();
694 if (sel_rows
.length
> 0) {
696 var ok
= confirm(__("Remove selected categories?"));
699 notify_progress("Removing selected categories...");
701 var query
= "backend.php?op=pref-feeds&subop=editCats&action=remove&ids="+
702 param_escape(sel_rows
.toString());
704 new Ajax
.Request(query
, {
705 onComplete: function(transport
) {
706 infobox_feed_cat_callback2(transport
);
713 alert(__("No categories are selected."));
720 function feedEditCancel() {
722 if (!xmlhttp_ready(xmlhttp
)) {
728 document
.getElementById("subscribe_to_feed_btn").disabled
= false;
729 document
.getElementById("top25_feeds_btn").disabled
= false;
731 // this button is not always available, no-op if not found
736 selectPrefRows('feed', false); // cleanup feed selection
741 function feedEditSave() {
745 if (!xmlhttp_ready(xmlhttp
)) {
750 // FIXME: add parameter validation
752 var query
= Form
.serialize("edit_feed_form");
754 notify_progress("Saving feed...");
756 xmlhttp
.open("POST", "backend.php", true);
757 xmlhttp
.onreadystatechange
=feedlist_callback
;
758 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
766 exception_error("feedEditSave", e
);
770 function userEditCancel() {
772 if (!xmlhttp_ready(xmlhttp
)) {
777 selectPrefRows('user', false); // cleanup feed selection
783 function filterEditCancel() {
785 if (!xmlhttp_ready(xmlhttp
)) {
791 document
.getElementById("create_filter_btn").disabled
= false;
792 selectPrefRows('filter', false); // cleanup feed selection
800 function userEditSave() {
802 if (!xmlhttp_ready(xmlhttp
)) {
807 var login
= document
.forms
["user_edit_form"].login
.value
;
809 if (login
.length
== 0) {
810 alert(__("Login field cannot be blank."));
814 notify_progress("Saving user...");
818 var query
= Form
.serialize("user_edit_form");
820 xmlhttp
.open("GET", "backend.php?" + query
, true);
821 xmlhttp
.onreadystatechange
=userlist_callback
;
828 function filterEditSave() {
830 if (!xmlhttp_ready(xmlhttp
)) {
835 /* if (!is_opera()) {
836 var reg_exp = document.forms["filter_edit_form"].reg_exp.value;
838 if (reg_exp.length == 0) {
839 alert("Filter expression field cannot be blank.");
844 notify_progress("Saving filter...");
846 var query
= Form
.serialize("filter_edit_form");
850 document
.getElementById("create_filter_btn").disabled
= false;
852 xmlhttp
.open("GET", "backend.php?" + query
, true);
853 xmlhttp
.onreadystatechange
=filterlist_callback
;
860 function editSelectedUser() {
861 var rows
= getSelectedUsers();
863 if (rows
.length
== 0) {
864 alert(__("No users are selected."));
868 if (rows
.length
> 1) {
869 alert(__("Please select only one user."));
878 function resetSelectedUserPass() {
879 var rows
= getSelectedUsers();
881 if (rows
.length
== 0) {
882 alert(__("No users are selected."));
886 if (rows
.length
> 1) {
887 alert(__("Please select only one user."));
891 var ok
= confirm(__("Reset password of selected user?"));
894 notify_progress("Resetting password for selected user...");
898 xmlhttp
.open("GET", "backend.php?op=pref-users&subop=resetPass&id=" +
899 param_escape(id
), true);
900 xmlhttp
.onreadystatechange
=userlist_callback
;
905 function selectedUserDetails() {
909 var rows
= getSelectedUsers();
911 if (rows
.length
== 0) {
912 alert(__("No users are selected."));
916 if (rows
.length
> 1) {
917 alert(__("Please select only one user."));
921 notify_progress("Loading, please wait...");
925 var query
= "backend.php?op=pref-users&subop=user-details&id=" + id
;
927 new Ajax
.Request(query
, {
928 onComplete: function(transport
) {
929 infobox_callback2(transport
);
932 exception_error("selectedUserDetails", e
);
937 function editSelectedFilter() {
938 var rows
= getSelectedFilters();
940 if (rows
.length
== 0) {
941 alert(__("No filters are selected."));
945 if (rows
.length
> 1) {
946 alert(__("Please select only one filter."));
957 function editSelectedFeed() {
958 var rows
= getSelectedFeeds();
960 if (rows
.length
== 0) {
961 alert(__("No feeds are selected."));
965 if (rows
.length
> 1) {
966 alert(__("Please select one feed."));
976 function editSelectedFeeds() {
979 var rows
= getSelectedFeeds();
981 if (rows
.length
== 0) {
982 alert(__("No feeds are selected."));
990 notify_progress("Loading, please wait...");
992 var query
= "backend.php?op=pref-feeds&subop=editfeeds&ids=" +
993 param_escape(rows
.toString());
995 new Ajax
.Request(query
, {
996 onComplete: function(transport
) {
997 infobox_callback2(transport
);
1001 exception_error("editSelectedFeeds", e
);
1005 function piggie(enable
) {
1007 debug("I LOVEDED IT!");
1008 var piggie
= document
.getElementById("piggie");
1010 Element
.show(piggie
);
1011 Position
.Center(piggie
);
1012 Effect
.Puff(piggie
);
1017 function validateOpmlImport() {
1019 var opml_file
= document
.getElementById("opml_file");
1021 if (opml_file
.value
.length
== 0) {
1022 alert(__("No OPML file to upload."));
1029 function updateFilterList(sort_key
) {
1031 if (!xmlhttp_ready(xmlhttp
)) {
1032 printLockingError();
1036 var filter_search
= document
.getElementById("filter_search");
1038 if (filter_search
) { search
= filter_search
.value
; }
1040 xmlhttp
.open("GET", "backend.php?op=pref-filters&sort=" +
1041 param_escape(sort_key
) +
1042 "&search=" + param_escape(search
), true);
1043 xmlhttp
.onreadystatechange
=filterlist_callback
;
1048 function updateLabelList(sort_key
) {
1052 var label_search
= document
.getElementById("label_search");
1054 if (label_search
) { search
= label_search
.value
; }
1056 var query
= "backend.php?op=pref-labels&sort=" +
1057 param_escape(sort_key
) +
1058 "&search=" + param_escape(search
);
1060 new Ajax
.Request(query
, {
1061 onComplete: function(transport
) {
1062 labellist_callback2(transport
);
1066 exception_error("updateLabelList", e
);
1070 function updatePrefsList() {
1072 if (!xmlhttp_ready(xmlhttp
)) {
1073 printLockingError();
1077 xmlhttp
.open("GET", "backend.php?op=pref-prefs", true);
1078 xmlhttp
.onreadystatechange
=prefslist_callback
;
1083 function selectTab(id
, noupdate
, subop
) {
1087 if (!id
) id
= active_tab
;
1091 if (!xmlhttp_ready(xmlhttp
)) {
1092 printLockingError();
1097 var c
= document
.getElementById('prefContent');
1103 debug("selectTab: " + id
+ "(NU: " + noupdate
+ ")");
1105 notify_progress("Loading, please wait...");
1107 // close active infobox if needed
1110 // clean up all current selections, just in case
1111 active_feed_cat
= false;
1113 // Effect.Fade("prefContent", {duration: 1, to: 0.01,
1114 // queue: { position:'end', scope: 'FEED_TAB', limit: 1 } } );
1116 if (id
== "feedConfig") {
1118 } else if (id
== "filterConfig") {
1120 } else if (id
== "labelConfig") {
1122 } else if (id
== "genConfig") {
1124 } else if (id
== "userConfig") {
1129 /* clean selection from all tabs */
1131 var tabs_holder
= document
.getElementById("prefTabs");
1132 var tab
= tabs_holder
.firstChild
;
1135 if (tab
.className
&& tab
.className
.match("prefsTabSelected")) {
1136 tab
.className
= "prefsTab";
1138 tab
= tab
.nextSibling
;
1141 /* mark new tab as selected */
1143 tab
= document
.getElementById(id
+ "Tab");
1146 if (!tab
.className
.match("Selected")) {
1147 tab
.className
= tab
.className
+ "Selected";
1154 exception_error("selectTab", e
);
1158 function backend_sanity_check_callback() {
1160 if (xmlhttp
.readyState
== 4) {
1164 if (sanity_check_done
) {
1165 fatalError(11, "Sanity check request received twice. This can indicate "+
1166 "presence of Firebug or some other disrupting extension. "+
1167 "Please disable it and try again.");
1171 if (!xmlhttp
.responseXML
) {
1172 fatalError(3, "Sanity Check: Received reply is not XML",
1173 xmlhttp
.responseText
);
1177 var reply
= xmlhttp
.responseXML
.firstChild
.firstChild
;
1180 fatalError(3, "Sanity Check: Invalid RPC reply", xmlhttp
.responseText
);
1184 var error_code
= reply
.getAttribute("error-code");
1186 if (error_code
&& error_code
!= 0) {
1187 return fatalError(error_code
, reply
.getAttribute("error-msg"));
1190 debug("sanity check ok");
1192 var params
= reply
.nextSibling
;
1195 debug('reading init-params...');
1196 var param
= params
.firstChild
;
1199 var k
= param
.getAttribute("key");
1200 var v
= param
.getAttribute("value");
1201 debug(k
+ " => " + v
);
1203 param
= param
.nextSibling
;
1207 sanity_check_done
= true;
1209 init_second_stage();
1212 exception_error("backend_sanity_check_callback", e
);
1217 function init_second_stage() {
1220 active_tab
= getInitParam("prefs_active_tab");
1221 if (!document
.getElementById(active_tab
+"Tab")) active_tab
= "genConfig";
1222 if (!active_tab
|| active_tab
== '0') active_tab
= "genConfig";
1224 document
.onkeydown
= pref_hotkey_handler
;
1226 var tab
= getURLParam('tab');
1228 caller_subop
= getURLParam('subop');
1230 if (getURLParam("subopparam")) {
1231 caller_subop
= caller_subop
+ ":" + getURLParam("subopparam");
1238 if (navigator
.userAgent
.match("Opera")) {
1239 setTimeout("selectTab()", 500);
1241 selectTab(active_tab
);
1245 loading_set_progress(60);
1248 exception_error("init_second_stage", e
);
1256 if (arguments
.callee
.done
) return;
1257 arguments
.callee
.done
= true;
1259 if (getURLParam('debug')) {
1260 Element
.show("debug_output");
1261 debug('debug mode activated');
1266 document
.getElementById("prefContent").innerHTML
=
1267 "<b>Fatal error:</b> This program needs XmlHttpRequest " +
1268 "to function properly. Your browser doesn't seem to support it.";
1272 loading_set_progress(30);
1274 xmlhttp
.open("GET", "backend.php?op=rpc&subop=sanityCheck", true);
1275 xmlhttp
.onreadystatechange
=backend_sanity_check_callback
;
1279 exception_error("init", e
);
1283 function categorizeSelectedFeeds() {
1285 if (!xmlhttp_ready(xmlhttp
)) {
1286 printLockingError();
1290 var sel_rows
= getSelectedFeeds();
1292 var cat_sel
= document
.getElementById("sfeed_set_fcat");
1293 var cat_id
= cat_sel
[cat_sel
.selectedIndex
].value
;
1295 if (sel_rows
.length
> 0) {
1297 notify_progress("Changing category of selected feeds...");
1299 xmlhttp
.open("GET", "backend.php?op=pref-feeds&subop=categorize&ids="+
1300 param_escape(sel_rows
.toString()) + "&cat_id=" + param_escape(cat_id
), true);
1301 xmlhttp
.onreadystatechange
=feedlist_callback
;
1306 alert(__("No feeds are selected."));
1312 function validatePrefsReset() {
1314 var ok
= confirm(__("Reset to defaults?"));
1318 var query
= Form
.serialize("pref_prefs_form");
1319 query
= query
+ "&subop=reset-config";
1322 xmlhttp
.open("POST", "backend.php", true);
1323 xmlhttp
.onreadystatechange
=prefs_reset_callback
;
1324 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
1325 xmlhttp
.send(query
);
1329 exception_error("validatePrefsSave", e
);
1336 function feedBrowserSubscribe() {
1339 var selected
= getSelectedFeedsFromBrowser();
1341 if (selected
.length
> 0) {
1343 xmlhttp
.open("GET", "backend.php?op=pref-feeds&subop=massSubscribe&ids="+
1344 param_escape(selected
.toString()), true);
1345 xmlhttp
.onreadystatechange
=feedlist_callback
;
1348 alert(__("No feeds are selected."));
1352 exception_error("feedBrowserSubscribe", e
);
1356 function updateBigFeedBrowserBtn() {
1357 notify_progress("Loading, please wait...");
1358 return updateBigFeedBrowser();
1361 function selectPrefRows(kind
, select
) {
1364 var opbarid
= false;
1369 if (kind
== "feed") {
1370 opbarid
= "feedOpToolbar";
1373 lname
= "prefFeedList";
1374 } else if (kind
== "fcat") {
1375 opbarid
= "catOpToolbar";
1378 lname
= "prefFeedCatList";
1379 } else if (kind
== "filter") {
1380 opbarid
= "filterOpToolbar";
1383 lname
= "prefFilterList";
1384 } else if (kind
== "label") {
1385 opbarid
= "labelOpToolbar";
1388 lname
= "prefLabelList";
1389 } else if (kind
== "user") {
1390 opbarid
= "userOpToolbar";
1393 lname
= "prefUserList";
1397 selectTableRowsByIdPrefix(lname
, nrow
, nchk
, select
);
1398 disableContainerChildren(opbarid
, !select
);
1405 function toggleSelectPrefRow(sender
, kind
) {
1407 toggleSelectRow(sender
);
1410 var opbarid
= false;
1413 if (kind
== "feed") {
1414 opbarid
= "feedOpToolbar";
1415 nsel
= getSelectedFeeds();
1416 } else if (kind
== "fcat") {
1417 opbarid
= "catOpToolbar";
1418 nsel
= getSelectedFeedCats();
1419 } else if (kind
== "filter") {
1420 opbarid
= "filterOpToolbar";
1421 nsel
= getSelectedFilters();
1422 } else if (kind
== "label") {
1423 opbarid
= "labelOpToolbar";
1424 nsel
= getSelectedLabels();
1425 } else if (kind
== "user") {
1426 opbarid
= "userOpToolbar";
1427 nsel
= getSelectedUsers();
1430 if (opbarid
&& nsel
!= -1) {
1431 disableContainerChildren(opbarid
, nsel
== false);
1437 function toggleSelectFBListRow(sender
) {
1438 toggleSelectListRow(sender
);
1439 disableContainerChildren("fbrOpToolbar", getSelectedFeedsFromBrowser() == 0);
1444 function pref_hotkey_handler(e
) {
1448 var shift_key
= false;
1451 shift_key
= e
.shiftKey
;
1457 keycode
= window
.event
.keyCode
;
1462 var keychar
= String
.fromCharCode(keycode
);
1464 if (keycode
== 27) { // escape
1465 if (Element
.visible("hotkey_help_overlay")) {
1466 Element
.hide("hotkey_help_overlay");
1468 hotkey_prefix
= false;
1472 if (!hotkeys_enabled
) {
1473 debug("hotkeys disabled");
1477 if (keycode
== 16) return; // ignore lone shift
1479 if ((keycode
== 67 || keycode
== 71) && !hotkey_prefix
) {
1480 hotkey_prefix
= keycode
;
1481 debug("KP: PREFIX=" + keycode
+ " CHAR=" + keychar
);
1485 if (Element
.visible("hotkey_help_overlay")) {
1486 Element
.hide("hotkey_help_overlay");
1489 if (keycode
== 13 || keycode
== 27) {
1492 seq
= seq
+ "" + keycode
;
1495 /* Global hotkeys */
1497 if (!hotkey_prefix
) {
1499 if (keycode
== 68 && shift_key
) { // d
1500 if (!Element
.visible("debug_output")) {
1501 Element
.show("debug_output");
1502 debug('debug mode activated');
1504 Element
.hide("debug_output");
1509 if ((keycode
== 191 || keychar
== '?') && shift_key
) { // ?
1510 if (!Element
.visible("hotkey_help_overlay")) {
1511 //Element.show("hotkey_help_overlay");
1512 Effect
.Appear("hotkey_help_overlay", {duration
: 0.3});
1514 Element
.hide("hotkey_help_overlay");
1519 if (keycode
== 191 || keychar
== '/') { // /
1520 var search_boxes
= new Array("label_search",
1521 "feed_search", "filter_search", "user_search", "feed_browser_search");
1523 for (var i
= 0; i
< search_boxes
.length
; i
++) {
1524 var elem
= document
.getElementById(search_boxes
[i
]);
1526 focus_element(search_boxes
[i
]);
1535 if (hotkey_prefix
== 67) { // c
1536 hotkey_prefix
= false;
1538 if (keycode
== 70) { // f
1539 displayDlg("quickAddFilter");
1543 if (keycode
== 83) { // s
1544 displayDlg("quickAddFeed");
1548 /* if (keycode == 76) { // l
1549 displayDlg("quickAddLabel");
1553 if (keycode
== 85) { // u
1557 if (keycode
== 67) { // c
1562 if (keycode
== 84 && shift_key
) { // T
1571 if (hotkey_prefix
== 71) { // g
1573 hotkey_prefix
= false;
1575 if (keycode
== 49 && document
.getElementById("genConfigTab")) { // 1
1576 selectTab("genConfig");
1580 if (keycode
== 50 && document
.getElementById("feedConfigTab")) { // 2
1581 selectTab("feedConfig");
1585 if (keycode
== 51 && document
.getElementById("filterConfigTab")) { // 4
1586 selectTab("filterConfig");
1590 if (keycode
== 52 && document
.getElementById("labelConfigTab")) { // 5
1591 selectTab("labelConfig");
1595 if (keycode
== 53 && document
.getElementById("userConfigTab")) { // 6
1596 selectTab("userConfig");
1600 if (keycode
== 88) { // x
1606 if (document
.getElementById("piggie")) {
1608 if (seq
.match("807371717369")) {
1616 if (hotkey_prefix
) {
1617 debug("KP: PREFIX=" + hotkey_prefix
+ " CODE=" + keycode
+ " CHAR=" + keychar
);
1619 debug("KP: CODE=" + keycode
+ " CHAR=" + keychar
);
1623 exception_error("pref_hotkey_handler", e
);
1627 function editFeedCats() {
1629 document
.getElementById("subscribe_to_feed_btn").disabled
= true;
1632 document
.getElementById("top25_feeds_btn").disabled
= true;
1634 // this button is not always available, no-op if not found
1637 var query
= "backend.php?op=pref-feeds&subop=editCats";
1639 new Ajax
.Request(query
, {
1640 onComplete: function(transport
) {
1641 infobox_feed_cat_callback2(transport
);
1644 exception_error("editFeedCats", e
);
1648 function showFeedsWithErrors() {
1649 displayDlg('feedUpdateErrors');
1652 function changeUserPassword() {
1656 if (!xmlhttp_ready(xmlhttp
)) {
1657 printLockingError();
1661 var f
= document
.forms
["change_pass_form"];
1664 if (f
.OLD_PASSWORD
.value
== "") {
1665 new Effect
.Highlight(f
.OLD_PASSWORD
);
1666 notify_error("Old password cannot be blank.");
1670 if (f
.NEW_PASSWORD
.value
== "") {
1671 new Effect
.Highlight(f
.NEW_PASSWORD
);
1672 notify_error("New password cannot be blank.");
1676 if (f
.CONFIRM_PASSWORD
.value
== "") {
1677 new Effect
.Highlight(f
.CONFIRM_PASSWORD
);
1678 notify_error("Entered passwords do not match.");
1682 if (f
.CONFIRM_PASSWORD
.value
!= f
.NEW_PASSWORD
.value
) {
1683 new Effect
.Highlight(f
.CONFIRM_PASSWORD
);
1684 new Effect
.Highlight(f
.NEW_PASSWORD
);
1685 notify_error("Entered passwords do not match.");
1691 var query
= Form
.serialize("change_pass_form");
1693 notify_progress("Trying to change password...");
1695 xmlhttp
.open("POST", "backend.php", true);
1696 xmlhttp
.onreadystatechange
=changepass_callback
;
1697 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
1698 xmlhttp
.send(query
);
1701 exception_error("changeUserPassword", e
);
1707 function changeUserEmail() {
1711 if (!xmlhttp_ready(xmlhttp
)) {
1712 printLockingError();
1716 var query
= Form
.serialize("change_email_form");
1718 notify_progress("Trying to change e-mail...");
1720 xmlhttp
.open("POST", "backend.php", true);
1721 xmlhttp
.onreadystatechange
=notify_callback
;
1722 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
1723 xmlhttp
.send(query
);
1726 exception_error("changeUserPassword", e
);
1733 function feedlistToggleSLAT() {
1734 notify_progress("Loading, please wait...");
1738 function pubRegenKey() {
1740 if (!xmlhttp_ready(xmlhttp
)) {
1741 printLockingError();
1745 var ok
= confirm(__("Replace current publishing address with a new one?"));
1749 notify_progress("Trying to change address...");
1751 xmlhttp
.open("GET", "backend.php?op=rpc&subop=regenPubKey");
1752 xmlhttp
.onreadystatechange
=replace_pubkey_callback
;
1759 function pubToClipboard() {
1763 if (!xmlhttp_ready(xmlhttp
)) {
1764 printLockingError();
1768 var link
= document
.getElementById("pubGenAddress");
1772 exception_error("pubToClipboard", e
);
1778 function validatePrefsSave() {
1781 var ok
= confirm(__("Save current configuration?"));
1785 var query
= Form
.serialize("pref_prefs_form");
1786 query
= query
+ "&subop=save-config";
1789 xmlhttp
.open("POST", "backend.php", true);
1790 xmlhttp
.onreadystatechange
=notify_callback
;
1791 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
1792 xmlhttp
.send(query
);
1796 exception_error("validatePrefsSave", e
);
1802 function feedActionChange() {
1804 var chooser
= document
.getElementById("feedActionChooser");
1805 var opid
= chooser
[chooser
.selectedIndex
].value
;
1807 chooser
.selectedIndex
= 0;
1810 exception_error("feedActionChange", e
);
1814 function feedActionGo(op
) {
1816 if (op
== "facEdit") {
1818 var rows
= getSelectedFeeds();
1820 if (rows
.length
> 1) {
1821 editSelectedFeeds();
1827 if (op
== "facClear") {
1828 clearSelectedFeeds();
1831 if (op
== "facPurge") {
1832 purgeSelectedFeeds();
1835 if (op
== "facEditCats") {
1839 if (op
== "facRescore") {
1840 rescoreSelectedFeeds();
1843 if (op
== "facUnsubscribe") {
1844 removeSelectedFeeds();
1848 exception_error("feedActionGo", e
);
1853 function clearFeedArticles(feed_id
) {
1855 notify_progress("Clearing feed...");
1857 var query
= "backend.php?op=pref-feeds&quiet=1&subop=clear&id=" + feed_id
;
1859 new Ajax
.Request(query
, {
1860 onComplete: function(transport
) {
1867 function rescoreSelectedFeeds() {
1869 if (!xmlhttp_ready(xmlhttp
)) {
1870 printLockingError();
1874 var sel_rows
= getSelectedFeeds();
1876 if (sel_rows
.length
> 0) {
1878 //var ok = confirm(__("Rescore last 100 articles in selected feeds?"));
1879 var ok
= confirm(__("Rescore articles in selected feeds?"));
1882 notify_progress("Rescoring selected feeds...", true);
1884 xmlhttp
.open("GET", "backend.php?op=pref-feeds&subop=rescore&quiet=1&ids="+
1885 param_escape(sel_rows
.toString()), true);
1886 xmlhttp
.onreadystatechange
=notify_callback
;
1890 alert(__("No feeds are selected."));
1896 function rescore_all_feeds() {
1897 var ok
= confirm(__("Rescore all articles? This operation may take a lot of time."));
1900 notify_progress("Rescoring feeds...", true);
1902 xmlhttp
.open("GET", "backend.php?op=pref-feeds&subop=rescoreAll&quiet=1", true);
1903 xmlhttp
.onreadystatechange
=notify_callback
;
1908 function removeFilter(id
, title
) {
1910 if (!xmlhttp_ready(xmlhttp
)) {
1911 printLockingError();
1915 var msg
= __("Remove filter %s?").replace("%s", title
);
1917 var ok
= confirm(msg
);
1922 notify_progress("Removing filter...");
1924 xmlhttp
.open("GET", "backend.php?op=pref-filters&subop=remove&ids="+
1925 param_escape(id
), true);
1926 xmlhttp
.onreadystatechange
=filterlist_callback
;
1933 function unsubscribeFeed(id
, title
) {
1935 if (!xmlhttp_ready(xmlhttp
)) {
1936 printLockingError();
1940 var msg
= __("Unsubscribe from %s?").replace("%s", title
);
1942 var ok
= confirm(msg
);
1947 notify_progress("Removing feed...");
1949 xmlhttp
.open("GET", "backend.php?op=pref-feeds&subop=remove&ids="+
1950 param_escape(id
), true);
1951 xmlhttp
.onreadystatechange
=filterlist_callback
;
1961 function feedsEditSave() {
1964 if (!xmlhttp_ready(xmlhttp
)) {
1965 printLockingError();
1969 var ok
= confirm(__("Save changes to selected feeds?"));
1973 var f
= document
.forms
["batch_edit_feed_form"];
1975 var query
= Form
.serialize("batch_edit_feed_form");
1977 /* Form.serialize ignores unchecked checkboxes */
1979 if (!query
.match("&hidden=") &&
1980 f
.hidden
.disabled
== false) {
1981 query
= query
+ "&hidden=false";
1984 if (!query
.match("&rtl_content=") &&
1985 f
.rtl_content
.disabled
== false) {
1986 query
= query
+ "&rtl_content=false";
1989 if (!query
.match("&private=") &&
1990 f
.private.disabled
== false) {
1991 query
= query
+ "&private=false";
1994 if (!query
.match("&cache_images=") &&
1995 f
.cache_images
.disabled
== false) {
1996 query
= query
+ "&cache_images=false";
1999 if (!query
.match("&include_in_digest=") &&
2000 f
.include_in_digest
.disabled
== false) {
2001 query
= query
+ "&include_in_digest=false";
2006 notify_progress("Saving feeds...");
2008 xmlhttp
.open("POST", "backend.php", true);
2009 xmlhttp
.onreadystatechange
=feedlist_callback
;
2010 xmlhttp
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
2011 xmlhttp
.send(query
);
2016 exception_error("feedsEditSave", e
);
2020 function batchFeedsToggleField(cb
, elem
, label
) {
2022 var f
= document
.forms
["batch_edit_feed_form"];
2023 var l
= document
.getElementById(label
);
2026 f
[elem
].disabled
= false;
2032 // new Effect.Highlight(f[elem], {duration: 1, startcolor: "#fff7d5",
2033 // queue: { position:'end', scope: 'BPEFQ', limit: 1 } } );
2036 f
[elem
].disabled
= true;
2039 l
.className
= "insensitive";
2044 exception_error("batchFeedsToggleField", e
);