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