]> git.wh0rd.org Git - tt-rss.git/blob - digest.js
a3cbb4879a92b20c3ba5eb9748369a904b4e1d32
[tt-rss.git] / digest.js
1 var last_feeds = [];
2
3 var _active_feed_id = false;
4 var _active_feed_offset = false;
5 var _update_timeout = false;
6 var _feedlist_expanded = false;
7
8 function catchup_feed(feed_id, callback) {
9         try {
10
11                 var fn = find_feed(last_feeds, feed_id).title;
12
13                 if (confirm(__("Mark all articles in %s as read?").replace("%s", fn))) {
14
15                         var is_cat = "";
16
17                         if (feed_id == -4) is_cat = "true";
18
19                         var query = "?op=rpc&subop=catchupFeed&feed_id=" + 
20                                 feed_id + "&is_cat=" + is_cat;
21
22                         new Ajax.Request("backend.php", {
23                                 parameters: query, 
24                                 onComplete: function(transport) {
25                                         if (callback) callback(transport);
26         
27                                         update();
28                                 } });
29                 }
30
31         } catch (e) {
32                 exception_error("catchup_article", e);
33         }
34 }
35
36
37 function catchup_article(article_id, callback) {
38         try {
39                 var query = "?op=rpc&subop=catchupSelected" +
40                         "&cmode=0&ids=" + article_id;
41
42                 new Ajax.Request("backend.php", {
43                         parameters: query, 
44                         onComplete: function(transport) {
45                                 if (callback) callback(transport);
46                         } });
47
48         } catch (e) {
49                 exception_error("catchup_article", e);
50         }
51 }
52
53 function set_selected_feed(feed_id) {
54         try {
55                 var feeds = $("feeds-content").getElementsByTagName("LI");
56
57                 for (var i = 0; i < feeds.length; i++) {
58                         if (feeds[i].id == "F-" + feed_id)
59                                 feeds[i].className = "selected";
60                         else
61                                 feeds[i].className = "";
62                 }
63
64                 _active_feed_id = feed_id;
65
66         } catch (e) {
67                 exception_error("mark_selected_feed", e);
68         }
69 }
70
71 function zoom(article_id) {
72         try {
73                 var elem = $('A-' + article_id);
74
75                 if (elem) {
76                         var divs = elem.getElementsByTagName('DIV');
77                         
78                         for (var i = 0; i < divs.length; i++) {
79                                 if (divs[i].className == 'excerpt') 
80                                         Element.hide(divs[i]);
81
82                                 if (divs[i].className == 'content') 
83                                         Element.show(divs[i]);
84                         }
85                 }
86
87                 catchup_article(article_id, 
88                         function() { update(); });
89
90         } catch (e) {
91                 exception_error("zoom", e);
92         }
93 }
94
95 function load_more() {
96         try {
97                 viewfeed(_active_feed_id, _active_feed_offset + 10);
98         } catch (e) {
99                 exception_error("load_more", e);
100         }
101 }
102
103 function update() {
104         try {
105                 console.log('updating feeds...');
106
107                 window.clearTimeout(_update_timeout);
108
109                 new Ajax.Request("backend.php", {
110                         parameters: "?op=rpc&subop=digest-init",
111                         onComplete: function(transport) {
112                                 fatal_error_check(transport);
113                                 parse_feeds(transport);
114                                 set_selected_feed(_active_feed_id);
115                                 } });
116
117                 _update_timeout = window.setTimeout('update()', 5*1000);
118         } catch (e) {
119                 exception_error("update", e);
120         }
121 }
122
123 function remove_headline_entry(article_id) {
124         try {
125                 var elem = $('A-' + article_id);
126
127                 if (elem) {
128                         elem.parentNode.removeChild(elem);
129                 }
130
131         } catch (e) {
132                 exception_error("remove_headline_entry", e);
133         }
134 }
135
136 function view(article_id, dismiss_only) {
137         try {
138                 remove_headline_entry(article_id);
139
140                 catchup_article(article_id, 
141                         function() { update(); });
142
143                 return dismiss_only != true;
144         } catch (e) {
145                 exception_error("view", e);
146         }
147 }
148
149 function viewfeed(feed_id, offset) {
150         try {
151
152                 if (!feed_id) feed_id = _active_feed_id;
153
154                 if (!offset) {
155                         offset = 0;
156                 } else {
157                         offset = _active_feed_offset + offset;
158                 }
159
160                 var query = "backend.php?op=rpc&subop=digest-update&feed_id=" + feed_id +
161                                 "&offset=" + offset;
162
163                 new Ajax.Request("backend.php", {
164                         parameters: query, 
165                         onComplete: function(transport) {
166                                 fatal_error_check(transport);
167                                 parse_headlines(transport, offset == 0);
168                                 set_selected_feed(feed_id);
169                                 _active_feed_offset = offset;
170                         } });
171
172         } catch (e) {
173                 exception_error("view", e);
174         }
175 }
176
177 function find_article(articles, article_id) {
178         try {
179                 for (var i = 0; i < articles.length; i++) {
180                         if (articles[i].id == article_id)
181                                 return articles[i];
182                 }
183
184                 return false;
185
186         } catch (e) {
187                 exception_error("find_article", e);
188         }
189 }
190
191 function find_feed(feeds, feed_id) {
192         try {
193                 for (var i = 0; i < feeds.length; i++) {
194                         if (feeds[i].id == feed_id)
195                                 return feeds[i];
196                 }
197
198                 return false;
199
200         } catch (e) {
201                 exception_error("find_feed", e);
202         }
203 }
204
205 function get_feed_icon(feed) {
206         try {
207                 if (feed.has_icon)
208                         return 'icons/' + feed.id + '.ico';
209
210                 if (feed.id == -1)
211                         return 'images/mark_set.png';
212
213                 if (feed.id == -2)
214                         return 'images/pub_set.png';
215
216                 if (feed.id == -3)
217                         return 'images/fresh.png';
218
219                 if (feed.id == -4) 
220                         return 'images/tag.png';
221
222                 if (feed.id < -10) 
223                         return 'images/label.png';
224
225                 return 'images/blank_icon.gif';
226
227         } catch (e) {
228                 exception_error("get_feed_icon", e);
229         }
230 }
231
232 function add_feed_entry(feed) {
233         try {
234                 var icon_part = "";
235
236                 icon_part = "<img src='" + get_feed_icon(feed) + "'/>";
237
238                 var tmp_html = "<li id=\"F-"+feed.id+"\" " +
239                                 "onmouseover=\"feed_mi(this)\" onmouseout=\"feed_mo(this)\">" + 
240                         icon_part +
241                         "<a href=\"#\" onclick=\"viewfeed("+feed.id+")\">" + feed.title + "</a>" +
242                         "<div class='unread-ctr'>" + 
243                                 "<img onclick=\"catchup_feed("+feed.id+")\" title=\"Dismiss\" class=\"dismiss\" style='display : none' src=\"images/digest_checkbox.png\">" +
244                                 "<span class=\"unread\">" + feed.unread + "</span>" + 
245                         "</div>" +      
246                         "</li>";
247
248                 $("feeds-content").innerHTML += tmp_html;
249
250         } catch (e) {
251                 exception_error("add_feed_entry", e);
252         }
253 }
254
255 function add_headline_entry(article, feed) {
256         try {
257
258                 var icon_part = "";
259
260                 icon_part = "<img class='icon' src='" + get_feed_icon(feed) + "'/>";
261
262                 var tmp_html = "<li id=\"A-"+article.id+"\">" + 
263                         icon_part +
264                         "<div class='digest-check'>" +
265                         "<img title='Set starred' onclick=\"toggleMark(this, "+article.id+")\" src='images/mark_unset.png'>" +
266                         "<img title='Set published' onclick=\"togglePub(this, "+article.id+")\" src='images/pub_unset.png'>" +
267                         "<img title='Dismiss' onclick=\"view("+article.id+", true)\" class='digest-check' src='images/digest_checkbox.png'>" +
268                         "</div>" + 
269                         "<a target=\"_blank\" href=\""+article.link+"\""+
270                                 "onclick=\"return view("+article.id+")\" class='title'>" + 
271                                 article.title + "</a>" +
272                         "<div class='body'>" + 
273                         "<div title=\"Click to expand article\" onclick=\"zoom("+article.id+")\" class='excerpt'>" + 
274                                 article.excerpt + "</div>" +
275                         "<div style='display : none' class='content'>" + 
276                                 article.content + "</div>" +
277                         "<div class='info'><a href=\#\" onclick=\"viewfeed("+feed.id+")\">" + 
278                                 feed.title + "</a> " + " @ " + 
279                                 new Date(article.updated * 1000) + "</div>" +
280                         "</div></li>";
281
282                 $("headlines-content").innerHTML += tmp_html;
283
284         } catch (e) {
285                 exception_error("add_headline_entry", e);
286         }
287 }
288
289 function expand_feeds() {
290         try {
291                 _feedlist_expanded = true;
292
293                 redraw_feedlist(last_feeds);
294
295         } catch (e) {
296                 exception_error("expand_feeds", e);
297         }
298 }
299
300 function redraw_feedlist(feeds) {
301         try {
302
303                 $('feeds-content').innerHTML = "";
304
305                 var limit = 10;
306
307                 if (_feedlist_expanded) limit = feeds.length;
308
309                 for (var i = 0; i < Math.min(limit, feeds.length); i++) {
310                         add_feed_entry(feeds[i]);
311                 }
312
313                 if (feeds.length > limit) {
314                         $('feeds-content').innerHTML += "<li id='F-MORE-PROMPT'>" +
315                                 "<img src='images/blank_icon.gif'>" + 
316                                 "<a href=\"#\" onclick=\"expand_feeds()\">" +
317                                 __("%d more...").replace("%d", feeds.length-10) + 
318                                 "</a>" + "</li>";
319                 }
320
321         } catch (e) {
322                 exception_error("redraw_feedlist", e);
323         }
324 }
325
326 function parse_feeds(transport) {
327         try {
328
329                 if (!transport.responseXML) return;
330
331                 var feeds = transport.responseXML.getElementsByTagName('feeds')[0];
332
333                 if (feeds) {
334                         feeds = eval("(" + feeds.firstChild.nodeValue + ")");
335
336                         feeds.sort( function (a,b) 
337                                 { 
338                                         if (b.unread != a.unread)
339                                                 return (b.unread - a.unread) 
340                                         else
341                                                 if (a.title > b.title)
342                                                         return 1;
343                                                 else if (a.title < b.title)
344                                                         return -1;
345                                                 else
346                                                         return 0;                                       
347                                 });
348
349                         last_feeds = feeds;
350
351                         redraw_feedlist(feeds);
352                 }
353
354         } catch (e) {
355                 exception_error("parse_feeds", e);
356         }
357 }
358
359 function parse_headlines(transport, replace) {
360         try {
361                 if (!transport.responseXML) return;
362
363                 var headlines = transport.responseXML.getElementsByTagName('headlines')[0];
364
365                 if (headlines) {
366                         headlines = eval("(" + headlines.firstChild.nodeValue + ")");
367
368                         if (replace) $('headlines-content').innerHTML = '';
369
370                         var pr = $('H-MORE-PROMPT');
371
372                         if (pr) pr.parentNode.removeChild(pr);
373
374                         for (var i = 0; i < headlines.length; i++) {
375                                 
376                                 if (!$('A-' + headlines[i].id)) {
377                                         add_headline_entry(headlines[i], 
378                                                         find_feed(last_feeds, headlines[i].feed_id));
379                                 }
380                         }
381
382                         if (pr) {
383                                 $('headlines-content').appendChild(pr);
384                         } else {
385                                 $('headlines-content').innerHTML += "<li id='H-MORE-PROMPT'>" +
386                                         "<div class='body'><a href=\"javascript:load_more()\">" +
387                                         __("More articles...") + "</a></div></li>";
388                         }
389
390                         new Effect.Appear('headlines-content');
391                 }
392
393         } catch (e) {
394                 exception_error("parse_headlines", e);
395         }
396 }
397
398 function init() {
399         try {
400                 
401                 new Ajax.Request("backend.php", {
402                         parameters: "backend.php?op=rpc&subop=digest-init",
403                         onComplete: function(transport) {
404                                 parse_feeds(transport);
405                                 window.setTimeout('viewfeed(-4)', 100);
406                                 _update_timeout = window.setTimeout('update()', 5*1000);
407                                 } });
408
409         } catch (e) {
410                 exception_error("digest_init", e);
411         }
412 }
413
414 function tMark_afh_off(effect) {
415         try {
416                 var elem = effect.effects[0].element;
417
418                 console.log("tMark_afh_off : " + elem.id);
419
420                 if (elem) {
421                         elem.src = elem.src.replace("mark_set", "mark_unset");
422                         elem.alt = __("Star article");
423                         Element.show(elem);
424                 }
425
426         } catch (e) {
427                 exception_error("tMark_afh_off", e);
428         }
429 }
430
431 function tPub_afh_off(effect) {
432         try {
433                 var elem = effect.effects[0].element;
434
435                 console.log("tPub_afh_off : " + elem.id);
436
437                 if (elem) {
438                         elem.src = elem.src.replace("pub_set", "pub_unset");
439                         elem.alt = __("Publish article");
440                         Element.show(elem);
441                 }
442
443         } catch (e) {
444                 exception_error("tPub_afh_off", e);
445         }
446 }
447
448 function toggleMark(mark_img, id) {
449
450         try {
451
452                 var query = "?op=rpc&id=" + id + "&subop=mark";
453         
454                 query = query + "&afid=" + _active_feed_id;
455                 query = query + "&omode=c";
456
457                 if (!mark_img) return;
458
459                 if (mark_img.src.match("mark_unset")) {
460                         mark_img.src = mark_img.src.replace("mark_unset", "mark_set");
461                         mark_img.alt = __("Unstar article");
462                         query = query + "&mark=1";
463                 } else {
464                         mark_img.alt = __("Please wait...");
465                         query = query + "&mark=0";
466         
467                         mark_img.src = mark_img.src.replace("mark_set", "mark_unset");
468                         mark_img.alt = __("Star article");
469                 }
470
471                 new Ajax.Request("backend.php", {
472                         parameters: query,
473                         onComplete: function(transport) { 
474                                 //
475                         } });
476
477         } catch (e) {
478                 exception_error("toggleMark", e);
479         }
480 }
481
482 function togglePub(mark_img, id, note) {
483
484         try {
485
486                 var query = "?op=rpc&id=" + id + "&subop=publ";
487         
488                 query = query + "&afid=" + _active_feed_id;
489
490                 if (note != undefined) {
491                         query = query + "&note=" + param_escape(note);
492                 } else {
493                         query = query + "&note=undefined";
494                 }
495
496                 query = query + "&omode=c";
497
498                 if (!mark_img) return;
499
500                 if (mark_img.src.match("pub_unset") || note != undefined) {
501                         mark_img.src = mark_img.src.replace("pub_unset", "pub_set");
502                         mark_img.alt = __("Unpublish article");
503                         query = query + "&pub=1";
504
505                 } else {
506                         mark_img.alt = __("Please wait...");
507                         query = query + "&pub=0";
508         
509                         mark_img.src = mark_img.src.replace("pub_set", "pub_unset");
510                         mark_img.alt = __("Publish article");
511                 }
512
513                 new Ajax.Request("backend.php", {
514                         parameters: query,
515                         onComplete: function(transport) { 
516                                 //
517                         } });
518
519         } catch (e) {
520                 exception_error("togglePub", e);
521         }
522 }
523
524 function fatal_error(code, msg) {
525         try {   
526
527                 if (code == 6) {
528                         window.location.href = "digest.php";
529                 } else if (code == 5) {
530                         window.location.href = "update.php";
531                 } else {
532         
533                         if (msg == "") msg = "Unknown error";
534
535                         console.error("Fatal error: " + code + "\n" + 
536                                 msg);
537                         
538                 }
539
540         } catch (e) {
541                 exception_error("fatalError", e);
542         }
543 }
544
545 function fatal_error_check(transport) {
546         try {
547                 if (transport.responseXML) {
548                         var error = transport.responseXML.getElementsByTagName("error")[0];
549
550                         if (error) {
551                                 var code = error.getAttribute("error-code");
552                                 var msg = error.getAttribute("error-msg");
553                                 if (code != 0) {
554                                         fatal_error(code, msg);
555                                         return false;
556                                 }
557                         }
558                 }
559         } catch (e) {
560                 exception_error("fatal_error_check", e);
561         }
562         return true;
563 }
564
565 function feed_mi(elem) {
566         try {
567                 var imgs = elem.getElementsByTagName('IMG');
568                 var spans = elem.getElementsByTagName('SPAN');
569
570                 for (var i = 0; i < imgs.length; i++) {
571                         if (imgs[i].className == "dismiss")
572                                 Element.show(imgs[i]);
573                 }
574
575                 for (var i = 0; i < spans.length; i++) {
576                         if (spans[i].className == "unread")
577                                 Element.hide(spans[i]);
578                 }
579
580
581         } catch (e) {
582                 exception_error("feed_mi", e);
583         }
584 }
585
586 function feed_mo(elem) {
587         try {
588                 var imgs = elem.getElementsByTagName('IMG');
589                 var spans = elem.getElementsByTagName('SPAN');
590
591                 for (var i = 0; i < imgs.length; i++) {
592                         if (imgs[i].className == "dismiss")
593                                 Element.hide(imgs[i]);
594                 }
595
596                 for (var i = 0; i < spans.length; i++) {
597                         if (spans[i].className == "unread")
598                                 Element.show(spans[i]);
599                 }
600
601         } catch (e) {
602                 exception_error("feed_mo", e);
603         }
604 }