]> git.wh0rd.org Git - tt-rss.git/blob - tt-rss.js
TAG 1.2.16
[tt-rss.git] / tt-rss.js
1 var total_unread = 0;
2 var first_run = true;
3 var display_tags = false;
4 var global_unread = -1;
5 var active_title_text = "";
6 var current_subtitle = "";
7 var daemon_enabled = false;
8 var daemon_refresh_only = false;
9 //var _qfd_deleted_feed = 0;
10 var firsttime_update = true;
11 var cookie_lifetime = 0;
12 var active_feed_id = 0;
13 var active_feed_is_cat = false;
14 var number_of_feeds = 0;
15 var sanity_check_done = false;
16
17 var init_params = new Object();
18
19 function tagsAreDisplayed() {
20         return display_tags;
21 }
22
23 function toggleTags(show_all) {
24
25         try {
26
27         debug("toggleTags: " + show_all + "; " + display_tags);
28
29         var p = document.getElementById("dispSwitchPrompt");
30
31         if (!show_all && !display_tags) {
32                 displayDlg("printTagCloud");
33         } else if (show_all) {
34                 closeInfoBox();
35                 display_tags = true;
36                 p.innerHTML = __("display feeds");
37                 notify_progress("Loading, please wait...", true);
38                 updateFeedList();
39         } else if (display_tags) {
40                 display_tags = false;
41                 p.innerHTML = __("tag cloud");
42                 notify_progress("Loading, please wait...", true);
43                 updateFeedList();
44         }
45
46         } catch (e) {
47                 exception_error("toggleTags", e);
48         }
49 }
50
51 function dlg_frefresh_callback(transport, deleted_feed) {
52         if (getActiveFeedId() == deleted_feed) {
53                 var h = document.getElementById("headlines-frame");
54                 if (h) {
55                         h.innerHTML = "<div class='whiteBox'>" + __('No feed selected.') + "</div>";
56                 }
57         }
58
59         setTimeout('updateFeedList(false, false)', 50);
60         closeInfoBox();
61 }
62
63 function refetch_callback2(transport) {
64         try {
65
66                 var date = new Date();
67
68                 parse_counters_reply(transport, true);
69
70                 debug("refetch_callback2: done");
71
72                 if (!daemon_enabled && !daemon_refresh_only) {
73                         notify_info("All feeds updated.");
74                         updateTitle("");
75                 } else {
76                         //notify("");
77                 }
78         } catch (e) {
79                 exception_error("refetch_callback", e);
80                 updateTitle("");
81         }
82 }
83
84 function backend_sanity_check_callback(transport) {
85
86         try {
87
88                 if (sanity_check_done) {
89                         fatalError(11, "Sanity check request received twice. This can indicate "+
90                       "presence of Firebug or some other disrupting extension. "+
91                                 "Please disable it and try again.");
92                         return;
93                 }
94
95                 if (!transport.responseXML) {
96                         fatalError(3, "[D001, Received reply is not XML]: " + transport.responseText);
97                         return;
98                 }
99
100                 var reply = transport.responseXML.firstChild.firstChild;
101
102                 if (!reply) {
103                         fatalError(3, "[D002, Invalid RPC reply]: " + transport.responseText);
104                         return;
105                 }
106
107                 var error_code = reply.getAttribute("error-code");
108         
109                 if (error_code && error_code != 0) {
110                         return fatalError(error_code, reply.getAttribute("error-msg"));
111                 }
112
113                 debug("sanity check ok");
114
115                 var params = reply.nextSibling;
116
117                 if (params) {
118                         debug('reading init-params...');
119                         var param = params.firstChild;
120
121                         while (param) {
122                                 var k = param.getAttribute("key");
123                                 var v = param.getAttribute("value");
124                                 debug(k + " => " + v);
125                                 init_params[k] = v;                                     
126                                 param = param.nextSibling;
127                         }
128                 }
129
130                 sanity_check_done = true;
131
132                 init_second_stage();
133
134         } catch (e) {
135                 exception_error("backend_sanity_check_callback", e);    
136         } 
137 }
138
139 function scheduleFeedUpdate(force) {
140
141         debug("in scheduleFeedUpdate");
142
143         if (!daemon_enabled && !daemon_refresh_only) {
144                 notify_progress("Updating feeds...", true);
145         }
146
147         var query_str = "backend.php?op=rpc&subop=";
148
149         if (force) {
150                 query_str = query_str + "forceUpdateAllFeeds";
151         } else {
152                 query_str = query_str + "updateAllFeeds";
153         }
154
155         var omode;
156
157         if (firsttime_update && !navigator.userAgent.match("Opera")) {
158                 firsttime_update = false;
159                 omode = "T";
160         } else {
161                 if (display_tags) {
162                         omode = "tl";
163                 } else {
164                         omode = "flc";
165                 }
166         }
167         
168         query_str = query_str + "&omode=" + omode;
169         query_str = query_str + "&uctr=" + global_unread;
170
171         var date = new Date();
172         var timestamp = Math.round(date.getTime() / 1000);
173         query_str = query_str + "&ts=" + timestamp
174
175         debug("REFETCH query: " + query_str);
176
177         new Ajax.Request(query_str, {
178                 onComplete: function(transport) { 
179                                 refetch_callback2(transport); 
180                         } });
181 }
182
183 function updateFeedList(silent, fetch) {
184
185 //      if (silent != true) {
186 //              notify("Loading feed list...");
187 //      }
188
189         debug("<b>updateFeedList</b>");
190
191         var query_str = "backend.php?op=feeds";
192
193         if (display_tags) {
194                 query_str = query_str + "&tags=1";
195         }
196
197         if (getActiveFeedId() && !activeFeedIsCat()) {
198                 query_str = query_str + "&actid=" + getActiveFeedId();
199         }
200
201         var date = new Date();
202         var timestamp = Math.round(date.getTime() / 1000);
203         query_str = query_str + "&ts=" + timestamp
204         
205         if (fetch) query_str = query_str + "&fetch=yes";
206
207 //      var feeds_frame = document.getElementById("feeds-frame");
208 //      feeds_frame.src = query_str;
209
210         debug("updateFeedList Q=" + query_str);
211
212         new Ajax.Request(query_str, {
213                 onComplete: function(transport) { 
214                         feedlist_callback2(transport); 
215                 } });
216
217 }
218
219 function catchupAllFeeds() {
220
221         var query_str = "backend.php?op=feeds&subop=catchupAll";
222
223         notify_progress("Marking all feeds as read...");
224
225         debug("catchupAllFeeds Q=" + query_str);
226
227         new Ajax.Request(query_str, {
228                 onComplete: function(transport) { 
229                         feedlist_callback2(transport); 
230                 } });
231
232         global_unread = 0;
233         updateTitle("");
234
235 }
236
237 function viewCurrentFeed(subop) {
238
239 //      if (getActiveFeedId()) {
240         if (getActiveFeedId() != undefined) {
241                 viewfeed(getActiveFeedId(), subop, active_feed_is_cat);
242         } else {
243                 disableContainerChildren("headlinesToolbar", false, document);
244 //              viewfeed(-1, subop); // FIXME
245         }
246         return false; // block unneeded form submits
247 }
248
249 function viewfeed(feed, subop) {
250         var f = window.frames["feeds-frame"];
251         f.viewfeed(feed, subop);
252 }
253
254 function timeout() {
255         scheduleFeedUpdate(false);
256
257         var refresh_time = getInitParam("feeds_frame_refresh");
258
259         if (!refresh_time) refresh_time = 600; 
260
261         setTimeout("timeout()", refresh_time*1000);
262 }
263
264 function resetSearch() {
265         var searchbox = document.getElementById("searchbox")
266
267         if (searchbox.value != "" && getActiveFeedId()) {       
268                 searchbox.value = "";
269                 viewfeed(getActiveFeedId(), "");
270         }
271 }
272
273 function searchCancel() {
274         closeInfoBox(true);
275 }
276
277 function search() {
278         closeInfoBox(); 
279         viewCurrentFeed(0, "");
280 }
281
282 // if argument is undefined, current subtitle is not updated
283 // use blank string to clear subtitle
284 function updateTitle(s) {
285         var tmp = "Tiny Tiny RSS";
286
287         if (s != undefined) {
288                 current_subtitle = s;
289         }
290
291         if (global_unread > 0) {
292                 tmp = tmp + " (" + global_unread + ")";
293         }
294
295         if (current_subtitle) {
296                 tmp = tmp + " - " + current_subtitle;
297         }
298
299         if (active_title_text.length > 0) {
300                 tmp = tmp + " > " + active_title_text;
301         }
302
303         document.title = tmp;
304 }
305
306 function genericSanityCheck() {
307
308 //      if (!Ajax.getTransport()) fatalError(1);
309
310         setCookie("ttrss_vf_test", "TEST");
311         
312         if (getCookie("ttrss_vf_test") != "TEST") {
313                 fatalError(2);
314         }
315
316         return true;
317 }
318
319 function init() {
320
321         try {
322
323                 // this whole shebang is based on http://www.birnamdesigns.com/misc/busted2.html
324
325                 if (arguments.callee.done) return;
326                 arguments.callee.done = true;           
327
328                 disableContainerChildren("headlinesToolbar", true);
329
330                 Form.disable("main_toolbar_form");
331
332                 if (!genericSanityCheck()) 
333                         return;
334
335                 if (getURLParam('debug')) {
336                         document.getElementById('debug_output').style.display = 'block';
337                         debug('debug mode activated');
338                 }
339
340                 var params = "&ua=" + param_escape(navigator.userAgent);
341
342                 new Ajax.Request("backend.php?op=rpc&subop=sanityCheck" + params,       {
343                         onComplete: function(transport) {
344                                         backend_sanity_check_callback(transport);
345                                 } });
346
347         } catch (e) {
348                 exception_error("init", e);
349         }
350 }
351
352 function resize_headlines() {
353
354         var h_frame = document.getElementById("headlines-frame");
355         var c_frame = document.getElementById("content-frame");
356         var f_frame = document.getElementById("footer");
357
358         if (!c_frame || !h_frame) return;
359
360         debug("resize_headlines");
361
362         if (!is_msie()) {
363                 h_frame.style.height = 30 + "%";
364                 c_frame.style.top = h_frame.offsetTop + h_frame.offsetHeight + 1 + "px";
365                 h_frame.style.height = h_frame.offsetHeight + "px";
366         } else {
367                 h_frame.style.height = document.documentElement.clientHeight * 0.3 + "px";
368                 c_frame.style.top = h_frame.offsetTop + h_frame.offsetHeight + 1 + "px";
369
370                 var c_bottom = document.documentElement.clientHeight;
371
372                 if (f_frame) {
373                         c_bottom = f_frame.offsetTop;
374                 }
375
376                 c_frame.style.height = c_bottom - (h_frame.offsetTop + 
377                         h_frame.offsetHeight + 1) + "px";
378                 h_frame.style.height = h_frame.offsetHeight + "px";
379
380         }
381 }
382
383 function init_second_stage() {
384
385         try {
386
387                 cookie_lifetime = getCookie("ttrss_cltime");
388
389                 delCookie("ttrss_vf_test");
390
391 //              document.onresize = resize_headlines;
392                 resize_headlines();
393
394                 var toolbar = document.forms["main_toolbar_form"];
395
396                 dropboxSelect(toolbar.view_mode, getInitParam("default_view_mode"));
397                 dropboxSelect(toolbar.limit, getInitParam("default_view_limit"));
398
399                 daemon_enabled = getInitParam("daemon_enabled") == 1;
400                 daemon_refresh_only = getInitParam("daemon_refresh_only") == 1;
401
402                 setTimeout('updateFeedList(false, false)', 50);
403
404                 debug("second stage ok");
405         
406         } catch (e) {
407                 exception_error("init_second_stage", e);
408         }
409 }
410
411 function quickMenuChange() {
412         var chooser = document.getElementById("quickMenuChooser");
413         var opid = chooser[chooser.selectedIndex].value;
414
415         chooser.selectedIndex = 0;
416         quickMenuGo(opid);
417 }
418
419 function quickMenuGo(opid) {
420         try {
421
422                 if (opid == "qmcPrefs") {
423                         gotoPreferences();
424                 }
425         
426                 if (opid == "qmcSearch") {
427                         displayDlg("search", getActiveFeedId() + ":" + activeFeedIsCat());
428                         return;
429                 }
430         
431                 if (opid == "qmcAddFeed") {
432                         displayDlg("quickAddFeed");
433                         return;
434                 }
435
436                 if (opid == "qmcEditFeed") {
437                         editFeedDlg(getActiveFeedId());
438                 }
439         
440                 if (opid == "qmcRemoveFeed") {
441                         var actid = getActiveFeedId();
442
443                         if (activeFeedIsCat()) {
444                                 alert(__("You can't unsubscribe from the category."));
445                                 return;
446                         }       
447
448                         if (!actid) {
449                                 alert(__("Please select some feed first."));
450                                 return;
451                         }
452
453                         var fn = getFeedName(actid);
454
455                         var pr = __("Unsubscribe from %s?").replace("%s", fn);
456
457                         if (confirm(pr)) {
458                                 unsubscribeFeed(actid);
459                         }
460                 
461                         return;
462                 }
463
464                 if (opid == "qmcClearFeed") {
465                         var actid = getActiveFeedId();
466
467                         if (!actid) {
468                                 alert(__("Please select some feed first."));
469                                 return;
470                         }
471
472                         if (activeFeedIsCat() || actid < 0) {
473                                 alert(__("You can't clear this type of feed."));
474                                 return;
475                         }       
476
477                         var fn = getFeedName(actid);
478
479                         var pr = __("Erase all non-starred articles in %s?").replace("%s", fn);
480
481                         if (confirm(pr)) {
482                                 clearFeedArticles(actid);
483                         }
484                 
485                         return;
486                 }
487         
488
489                 if (opid == "qmcUpdateFeeds") {
490                         scheduleFeedUpdate(true);
491                         return;
492                 }
493         
494                 if (opid == "qmcCatchupAll") {
495                         catchupAllFeeds();
496                         return;
497                 }
498         
499                 if (opid == "qmcShowOnlyUnread") {
500                         toggleDispRead();
501                         return;
502                 }
503         
504                 if (opid == "qmcAddFilter") {
505                         displayDlg("quickAddFilter", getActiveFeedId());
506                 }
507
508         } catch (e) {
509                 exception_error("quickMenuGo", e);
510         }
511 }
512
513 function unsubscribeFeed(feed_id) {
514
515         notify_progress("Removing feed...");
516
517         var query = "backend.php?op=pref-feeds&quiet=1&subop=remove&ids=" + feed_id;
518
519         new Ajax.Request(query, {
520                 onComplete: function(transport) {
521                                 dlg_frefresh_callback(transport, feed_id);
522                         } });
523
524
525         return false;
526 }
527
528
529 function updateFeedTitle(t) {
530         active_title_text = t;
531         updateTitle();
532 }
533
534 function toggleDispRead() {
535         try {
536
537                 var hide_read_feeds = (getInitParam("hide_read_feeds") == "1");
538
539                 hide_read_feeds = !hide_read_feeds;
540
541                 debug("toggle_disp_read => " + hide_read_feeds);
542
543                 hideOrShowFeeds(getFeedsContext().document, hide_read_feeds);
544
545                 storeInitParam("hide_read_feeds", hide_read_feeds, true);
546                                 
547         } catch (e) {
548                 exception_error("toggleDispRead", e);
549         }
550 }
551
552 function parse_runtime_info(elem) {
553         if (!elem) {
554                 debug("parse_runtime_info: elem is null, aborting");
555                 return;
556         }
557
558         var param = elem.firstChild;
559
560         debug("parse_runtime_info: " + param);
561
562         while (param) {
563                 var k = param.getAttribute("key");
564                 var v = param.getAttribute("value");
565
566                 debug("RI: " + k + " => " + v);
567
568                 if (k == "new_version_available") {
569                         var icon = document.getElementById("newVersionIcon");
570                         if (icon) {
571                                 if (v == "1") {
572                                         icon.style.display = "inline";
573                                 } else {
574                                         icon.style.display = "none";
575                                 }
576                         }
577                 }
578
579                 var error_flag;
580
581                 if (k == "daemon_is_running" && v != 1) {
582                         notify_error("<span onclick=\"javascript:explainError(1)\">Update daemon is not running.</span>", true);
583                         error_flag = true;
584                 }
585
586                 if (k == "daemon_stamp_ok" && v != 1) {
587                         notify_error("<span onclick=\"javascript:explainError(3)\">Update daemon is not updating feeds.</span>", true);
588                         error_flag = true;
589                 }
590
591                 if (!error_flag) {
592                         notify('');
593                 }
594
595 /*              var w = document.getElementById("noDaemonWarning");
596                 
597                 if (w) {
598                         if (k == "daemon_is_running" && v != 1) {
599                                 w.style.display = "block";
600                         } else {
601                                 w.style.display = "none";
602                         }
603                 } */
604                 param = param.nextSibling;
605         }
606 }
607
608 function catchupCurrentFeed() {
609
610         var fn = getFeedName(getActiveFeedId(), active_feed_is_cat);
611         
612         var str = __("Mark all articles in %s as read?").replace("%s", fn);
613
614 /*      if (active_feed_is_cat) {
615                 str = "Mark all articles in this category as read?";
616         } */
617
618         if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
619                 return viewCurrentFeed('MarkAllRead')
620         }
621 }
622
623 function editFeedDlg(feed) {
624         try {
625
626                 disableHotkeys();
627         
628                 if (!feed) {
629                         alert(__("Please select some feed first."));
630                         return;
631                 }
632         
633                 if ((feed <= 0 && feed > -10) || activeFeedIsCat() || tagsAreDisplayed()) {
634                         alert(__("You can't edit this kind of feed."));
635                         return;
636                 }
637         
638                 var query = "";
639         
640                 if (feed > 0) {
641                         query = "backend.php?op=pref-feeds&subop=editfeed&id=" +        param_escape(feed);
642                 } else {
643                         query = "backend.php?op=pref-labels&subop=edit&id=" +   param_escape(-feed-11);
644                 }
645         
646                 new Ajax.Request(query, {
647                         onComplete: function(transport) { 
648                                 infobox_callback2(transport); 
649                         } });
650
651         } catch (e) {
652                 exception_error("editFeedDlg", e);
653         }
654 }
655
656 /* this functions duplicate those of prefs.js feed editor, with
657         some differences because there is no feedlist */
658
659 function feedEditCancel() {
660         closeInfoBox();
661         return false;
662 }
663
664 function feedEditSave() {
665
666         try {
667         
668                 // FIXME: add parameter validation
669
670                 var query = Form.serialize("edit_feed_form");
671
672                 notify_progress("Saving feed...");
673
674                 new Ajax.Request("backend.php", {
675                         parameters: query,
676                         onComplete: function(transport) { 
677                                 dlg_frefresh_callback(transport); 
678                         } });
679
680
681                 closeInfoBox();
682
683                 return false;
684
685         } catch (e) {
686                 exception_error("feedEditSave (main)", e);
687         } 
688 }
689
690 function labelEditCancel() {
691         closeInfoBox();
692         return false;
693 }
694
695 function labelEditSave() {
696
697         try {
698
699                 closeInfoBox();
700         
701                 notify_progress("Saving label...");
702         
703                 query = Form.serialize("label_edit_form");
704         
705                 new Ajax.Request("backend.php?" + query, {
706                         onComplete: function(transport) { 
707                                 dlg_frefresh_callback(transport); 
708                         } });
709
710                 return false;
711
712         } catch (e) {
713                 exception_error("feedEditSave (main)", e);
714         } 
715
716 }
717
718 function clearFeedArticles(feed_id) {
719
720         notify_progress("Clearing feed...");
721
722         var query = "backend.php?op=pref-feeds&quiet=1&subop=clear&id=" + feed_id;
723
724         new Ajax.Request(query, {
725                 onComplete: function(transport) {
726                                 dlg_frefresh_callback(transport, feed_id);
727                         } });
728
729         return false;
730 }
731
732