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