]> git.wh0rd.org - tt-rss.git/blob - tt-rss.js
null category fixes
[tt-rss.git] / tt-rss.js
1 var xmlhttp = false;
2 var total_unread = 0;
3 var first_run = true;
4 var display_tags = false;
5 var global_unread = -1;
6 var active_title_text = "";
7 var current_subtitle = "";
8 var daemon_enabled = false;
9 var daemon_refresh_only = false;
10 var _qfd_deleted_feed = 0;
11 var firsttime_update = true;
12 var last_refetch = 0;
13 var cookie_lifetime = 0;
14 var active_feed_id = 0;
15 var active_feed_is_cat = false;
16
17 var xmlhttp = Ajax.getTransport();
18
19 var init_params = new Object();
20
21 function toggleTags() {
22 display_tags = !display_tags;
23
24 var p = document.getElementById("dispSwitchPrompt");
25
26 if (display_tags) {
27 p.innerHTML = "display feeds";
28 } else {
29 p.innerHTML = "display tags";
30 }
31
32 updateFeedList();
33 }
34
35 function dlg_frefresh_callback() {
36 if (xmlhttp.readyState == 4) {
37 notify(xmlhttp.responseText);
38 updateFeedList(false, false);
39 if (_qfd_deleted_feed) {
40 var hframe = document.getElementById("headlines-frame");
41 if (hframe) {
42 hframe.src = "backend.php?op=error&msg=No%20feed%20selected.";
43 }
44 }
45 closeInfoBox();
46 }
47 }
48
49 function refetch_callback() {
50 if (xmlhttp.readyState == 4) {
51 try {
52
53 var date = new Date();
54
55 last_refetch = date.getTime() / 1000;
56
57 if (!xmlhttp.responseXML) {
58 notify("refetch_callback: backend did not return valid XML", true, true);
59 return;
60 }
61
62 var reply = xmlhttp.responseXML.firstChild;
63
64 if (!reply) {
65 notify("refetch_callback: backend did not return expected XML object", true, true);
66 updateTitle("");
67 return;
68 }
69
70 var error_code = reply.getAttribute("error-code");
71
72 if (error_code && error_code != 0) {
73 return fatalError(error_code, reply.getAttribute("error-msg"));
74 }
75
76 var counters = reply.firstChild;
77
78 parse_counters(counters, true);
79
80 var runtime_info = counters.nextSibling;
81
82 parse_runtime_info(runtime_info);
83
84 debug("refetch_callback: done");
85
86 if (!daemon_enabled && !daemon_refresh_only) {
87 notify("All feeds updated.");
88 updateTitle("");
89 } else {
90 notify("");
91 }
92 } catch (e) {
93 exception_error("refetch_callback", e);
94 updateTitle("");
95 }
96 }
97 }
98
99 function backend_sanity_check_callback() {
100
101 if (xmlhttp.readyState == 4) {
102
103 try {
104
105 if (!xmlhttp.responseXML) {
106 fatalError(3, "[D001, Received reply is not XML]: " + xmlhttp.responseText);
107 return;
108 }
109
110 var reply = xmlhttp.responseXML.firstChild.firstChild;
111
112 if (!reply) {
113 fatalError(3, "[D002, Invalid RPC reply]: " + xmlhttp.responseText);
114 return;
115 }
116
117 var error_code = reply.getAttribute("error-code");
118
119 if (error_code && error_code != 0) {
120 return fatalError(error_code, reply.getAttribute("error-msg"));
121 }
122
123 debug("sanity check ok");
124
125 var params = reply.nextSibling;
126
127 if (params) {
128 debug('reading init-params...');
129 var param = params.firstChild;
130
131 while (param) {
132 var k = param.getAttribute("key");
133 var v = param.getAttribute("value");
134 debug(k + " => " + v);
135 init_params[k] = v;
136 param = param.nextSibling;
137 }
138 }
139
140 init_second_stage();
141
142 } catch (e) {
143 exception_error("backend_sanity_check_callback", e);
144 }
145 }
146 }
147
148 function scheduleFeedUpdate(force) {
149
150 if (!daemon_enabled && !daemon_refresh_only) {
151 notify("Updating feeds, please wait.", true);
152 updateTitle("Updating");
153 }
154
155 var query_str = "backend.php?op=rpc&subop=";
156
157 if (force) {
158 query_str = query_str + "forceUpdateAllFeeds";
159 } else {
160 query_str = query_str + "updateAllFeeds";
161 }
162
163 var omode;
164
165 if (firsttime_update && !navigator.userAgent.match("Opera")) {
166 firsttime_update = false;
167 omode = "T";
168 } else {
169 if (display_tags) {
170 omode = "t";
171 } else {
172 omode = "flc";
173 }
174 }
175
176 query_str = query_str + "&omode=" + omode;
177 query_str = query_str + "&uctr=" + global_unread;
178
179 debug("in scheduleFeedUpdate");
180
181 var date = new Date();
182
183 if (!xmlhttp_ready(xmlhttp) && last_refetch < date.getTime() / 1000 - 60) {
184 debug("<b>xmlhttp seems to be stuck, aborting</b>");
185 xmlhttp.abort();
186 }
187
188 if (xmlhttp_ready(xmlhttp)) {
189 xmlhttp.open("GET", query_str, true);
190 xmlhttp.onreadystatechange=refetch_callback;
191 xmlhttp.send(null);
192 } else {
193 debug("xmlhttp busy");
194 //printLockingError();
195 }
196 }
197
198 function updateFeedList(silent, fetch) {
199
200 // if (silent != true) {
201 // notify("Loading feed list...");
202 // }
203
204 var query_str = "backend.php?op=feeds";
205
206 if (display_tags) {
207 query_str = query_str + "&tags=1";
208 }
209
210 if (getActiveFeedId() != undefined) {
211 query_str = query_str + "&actid=" + getActiveFeedId();
212 }
213
214 if (navigator.userAgent.match("Opera")) {
215 var date = new Date();
216 var timestamp = Math.round(date.getTime() / 1000);
217 query_str = query_str + "&ts=" + timestamp
218 }
219
220 if (fetch) query_str = query_str + "&fetch=yes";
221
222 var feeds_frame = document.getElementById("feeds-frame");
223
224 feeds_frame.src = query_str;
225 }
226
227 function catchupAllFeeds() {
228
229 var query_str = "backend.php?op=feeds&subop=catchupAll";
230
231 notify("Marking all feeds as read...");
232
233 var feeds_frame = document.getElementById("feeds-frame");
234
235 feeds_frame.src = query_str;
236
237 global_unread = 0;
238 updateTitle("");
239
240 }
241
242 function viewCurrentFeed(subop) {
243
244 // if (getActiveFeedId()) {
245 if (getActiveFeedId() != undefined) {
246 viewfeed(getActiveFeedId(), subop);
247 } else {
248 disableContainerChildren("headlinesToolbar", false, document);
249 // viewfeed(-1, subop); // FIXME
250 }
251 return false; // block unneeded form submits
252 }
253
254 function viewfeed(feed, subop) {
255 var f = window.frames["feeds-frame"];
256 f.viewfeed(feed, subop);
257 }
258
259 function timeout() {
260 scheduleFeedUpdate(false);
261
262 var refresh_time = getInitParam("feeds_frame_refresh");
263
264 if (!refresh_time) refresh_time = 600;
265
266 setTimeout("timeout()", refresh_time*1000);
267 }
268
269 function resetSearch() {
270 var searchbox = document.getElementById("searchbox")
271
272 if (searchbox.value != "" && getActiveFeedId()) {
273 searchbox.value = "";
274 viewfeed(getActiveFeedId(), "");
275 }
276 }
277
278 function searchCancel() {
279 closeInfoBox(true);
280 }
281
282 function search() {
283 closeInfoBox();
284 viewCurrentFeed(0, "");
285 }
286
287 function localPiggieFunction(enable) {
288 if (enable) {
289 var query_str = "backend.php?op=feeds&subop=piggie";
290
291 if (xmlhttp_ready(xmlhttp)) {
292
293 xmlhttp.open("GET", query_str, true);
294 xmlhttp.onreadystatechange=feedlist_callback;
295 xmlhttp.send(null);
296 }
297 }
298 }
299
300 // if argument is undefined, current subtitle is not updated
301 // use blank string to clear subtitle
302 function updateTitle(s) {
303 var tmp = "Tiny Tiny RSS";
304
305 if (s != undefined) {
306 current_subtitle = s;
307 }
308
309 if (global_unread > 0) {
310 tmp = tmp + " (" + global_unread + ")";
311 }
312
313 if (current_subtitle) {
314 tmp = tmp + " - " + current_subtitle;
315 }
316
317 if (active_title_text.length > 0) {
318 tmp = tmp + " > " + active_title_text;
319 }
320
321 document.title = tmp;
322 }
323
324 function genericSanityCheck() {
325
326 if (!xmlhttp) fatalError(1);
327
328 setCookie("ttrss_vf_test", "TEST");
329
330 if (getCookie("ttrss_vf_test") != "TEST") {
331 fatalError(2);
332 }
333
334 return true;
335 }
336
337 function init() {
338
339 try {
340
341 // this whole shebang is based on http://www.birnamdesigns.com/misc/busted2.html
342
343 if (arguments.callee.done) return;
344 arguments.callee.done = true;
345
346 disableContainerChildren("headlinesToolbar", true);
347
348 Form.disable("main_toolbar_form");
349
350 if (!genericSanityCheck())
351 return;
352
353 if (getURLParam('debug')) {
354 document.getElementById('debug_output').style.display = 'block';
355 debug('debug mode activated');
356 }
357
358 xmlhttp.open("GET", "backend.php?op=rpc&subop=sanityCheck", true);
359 xmlhttp.onreadystatechange=backend_sanity_check_callback;
360 xmlhttp.send(null);
361
362 } catch (e) {
363 exception_error("init", e);
364 }
365 }
366
367 function resize_feeds_frame() {
368 var f = document.getElementById("feeds-frame");
369 var tf = document.getElementById("mainFooter");
370 var th = document.getElementById("mainHeader");
371
372 var footer_height = 0;
373 var header_height = 0;
374
375 if (tf) {
376 footer_height = tf.scrollHeight;
377 }
378
379 if (th) {
380 header_height = th.scrollHeight;
381 }
382
383 f.style.height = document.body.scrollHeight - footer_height -
384 header_height - 50 + "px";
385 }
386
387 function init_second_stage() {
388
389 try {
390
391 cookie_lifetime = getCookie("ttrss_cltime");
392
393 delCookie("ttrss_vf_test");
394
395 updateFeedList(false, false);
396 document.onkeydown = hotkey_handler;
397
398 var tb = parent.document.forms["main_toolbar_form"];
399
400 dropboxSelect(tb.view_mode, getInitParam("toolbar_view_mode"));
401 dropboxSelect(tb.limit, getInitParam("toolbar_limit"));
402
403 daemon_enabled = getInitParam("daemon_enabled") == 1;
404 daemon_refresh_only = getInitParam("daemon_refresh_only") == 1;
405
406 // FIXME should be callled after window resize
407
408 var h = document.getElementById("headlines");
409 var c = document.getElementById("content");
410
411 if (navigator.userAgent.match("Opera")) {
412 resize_feeds_frame();
413 }
414
415 debug("second stage ok");
416
417 } catch (e) {
418 exception_error("init_second_stage", e);
419 }
420 }
421
422 function quickMenuChange() {
423 var chooser = document.getElementById("quickMenuChooser");
424 var opid = chooser[chooser.selectedIndex].value;
425
426 chooser.selectedIndex = 0;
427 quickMenuGo(opid);
428 }
429
430 function quickMenuGo(opid) {
431 try {
432
433 if (opid == "qmcPrefs") {
434 gotoPreferences();
435 }
436
437 if (opid == "qmcSearch") {
438 displayDlg("search", getActiveFeedId() + ":" + activeFeedIsCat());
439 return;
440 }
441
442 if (opid == "qmcAddFeed") {
443 displayDlg("quickAddFeed");
444 return;
445 }
446
447 if (opid == "qmcRemoveFeed") {
448 var actid = getActiveFeedId();
449
450 if (actid == undefined) {
451 alert("Please select some feed first.");
452 return;
453 }
454
455 var fn = getFeedName(actid);
456
457 if (confirm("Unsubscribe from " + fn + "?")) {
458 qfdDelete(actid);
459 }
460
461 return;
462 }
463
464 if (opid == "qmcUpdateFeeds") {
465 scheduleFeedUpdate(true);
466 return;
467 }
468
469 if (opid == "qmcCatchupAll") {
470 catchupAllFeeds();
471 return;
472 }
473
474 if (opid == "qmcShowOnlyUnread") {
475 toggleDispRead();
476 return;
477 }
478
479 if (opid == "qmcAddFilter") {
480 displayDlg("quickAddFilter", getActiveFeedId());
481 }
482 } catch (e) {
483 exception_error("quickMenuGo", e);
484 }
485 }
486
487 function qfdDelete(feed_id) {
488
489 notify("Removing feed...");
490
491 if (!xmlhttp_ready(xmlhttp)) {
492 printLockingError();
493 return
494 }
495
496 _qfd_deleted_feed = feed_id;
497
498 xmlhttp.open("GET", "backend.php?op=pref-feeds&quiet=1&subop=remove&ids=" + feed_id);
499 xmlhttp.onreadystatechange=dlg_frefresh_callback;
500 xmlhttp.send(null);
501 }
502
503
504 function updateFeedTitle(t) {
505 active_title_text = t;
506 updateTitle();
507 }
508
509 function toggleDispRead() {
510 try {
511
512 if (!xmlhttp_ready(xmlhttp)) {
513 printLockingError();
514 return
515 }
516
517 var hide_read_feeds = (getInitParam("hide_read_feeds") == "1");
518
519 hide_read_feeds = !hide_read_feeds;
520
521 debug("toggle_disp_read => " + hide_read_feeds);
522
523 hideOrShowFeeds(getFeedsContext().document, hide_read_feeds);
524
525 var query = "backend.php?op=rpc&subop=setpref" +
526 "&key=HIDE_READ_FEEDS&value=" + param_escape(hide_read_feeds);
527
528 storeInitParam("hide_read_feeds", hide_read_feeds, true);
529
530 new Ajax.Request(query);
531
532 } catch (e) {
533 exception_error("toggleDispRead", e);
534 }
535 }
536
537 function parse_runtime_info(elem) {
538 var param = elem.firstChild;
539
540 debug("parse_runtime_info");
541
542 while (param) {
543 var k = param.getAttribute("key");
544 var v = param.getAttribute("value");
545
546 debug("RI: " + k + " => " + v);
547
548 var w = document.getElementById("noDaemonWarning");
549
550 if (w) {
551 if (k == "daemon_is_running" && v != 1) {
552 w.style.display = "block";
553 } else {
554 w.style.display = "none";
555 }
556 }
557 param = param.nextSibling;
558 }
559 }
560
561 function catchupCurrentFeed() {
562
563 var fn = getFeedName(getActiveFeedId(), active_feed_is_cat);
564
565 var str = "Mark all articles in " + fn + " as read?";
566
567 /* if (active_feed_is_cat) {
568 str = "Mark all articles in this category as read?";
569 } */
570
571 if (confirm(str)) {
572 return viewCurrentFeed(0, 'MarkAllRead')
573 }
574 }
575