]> git.wh0rd.org - tt-rss.git/blob - tt-rss.js
release 1.0
[tt-rss.git] / tt-rss.js
1 /*
2 This program is Copyright (c) 2003-2005 Andrew Dolgov <cthulhoo@gmail.com>
3 Licensed under GPL v.2 or (at your preference) any later version.
4 */
5
6 var xmlhttp = false;
7 var xmlhttp_rpc = false;
8 var xmlhttp_view = false;
9
10 var total_unread = 0;
11 var first_run = true;
12
13 var active_post_id = false;
14 var active_feed_id = false;
15 var active_offset = false;
16
17 var total_feed_entries = false;
18
19 var _viewfeed_autoselect_first = false;
20 var _viewfeed_autoselect_last = false;
21
22 var search_query = "";
23
24 /*@cc_on @*/
25 /*@if (@_jscript_version >= 5)
26 // JScript gives us Conditional compilation, we can cope with old IE versions.
27 // and security blocked creation of the objects.
28 try {
29 xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
30 } catch (e) {
31 try {
32 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
33 xmlhttp_rpc = new ActiveXObject("Microsoft.XMLHTTP");
34 xmlhttp_view = new ActiveXObject("Microsoft.XMLHTTP");
35 } catch (E) {
36 xmlhttp = false;
37 xmlhttp_rpc = false;
38 xmlhttp_view = false;
39 }
40 }
41 @end @*/
42
43 if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
44 xmlhttp = new XMLHttpRequest();
45 xmlhttp_rpc = new XMLHttpRequest();
46 xmlhttp_view = new XMLHttpRequest();
47 }
48
49 function feedlist_callback() {
50 var container = document.getElementById('feeds');
51 if (xmlhttp.readyState == 4) {
52 container.innerHTML=xmlhttp.responseText;
53
54 if (first_run) {
55 scheduleFeedUpdate(false);
56 first_run = false;
57 } else {
58 notify("");
59 }
60 }
61 }
62
63 function viewfeed_callback() {
64 var container = document.getElementById('headlines');
65 if (xmlhttp.readyState == 4) {
66 container.innerHTML = xmlhttp.responseText;
67
68 var factive = document.getElementById("FACTIVE");
69 var funread = document.getElementById("FUNREAD");
70 var ftotal = document.getElementById("FTOTAL");
71
72 if (_viewfeed_autoselect_first == true) {
73 _viewfeed_autoselect_first = false;
74 view(getFirstVisibleHeadlineId(), active_feed_id);
75 }
76
77 if (_viewfeed_autoselect_last == true) {
78 _viewfeed_autoselect_last = false;
79 view(getLastVisibleHeadlineId(), active_feed_id);
80 }
81
82 if (ftotal && factive && funread) {
83 var feed_id = factive.innerHTML;
84
85 var feedr = document.getElementById("FEEDR-" + feed_id);
86 var feedt = document.getElementById("FEEDT-" + feed_id);
87 var feedu = document.getElementById("FEEDU-" + feed_id);
88
89 feedt.innerHTML = ftotal.innerHTML;
90 feedu.innerHTML = funread.innerHTML;
91
92 total_feed_entries = ftotal.innerHTML;
93
94 if (feedu.innerHTML > 0 && !feedr.className.match("Unread")) {
95 feedr.className = feedr.className + "Unread";
96 } else if (feedu.innerHTML <= 0) {
97 feedr.className = feedr.className.replace("Unread", "");
98 }
99
100 cleanSelected("feedsList");
101
102 feedr.className = feedr.className + "Selected";
103 }
104
105 var searchbox = document.getElementById("searchbox");
106 searchbox.value = search_query;
107
108 markHeadline(active_post_id);
109
110 notify("");
111
112 }
113 }
114
115 function view_callback() {
116 var container = document.getElementById('content');
117 if (xmlhttp_view.readyState == 4) {
118 container.innerHTML=xmlhttp_view.responseText;
119 markHeadline(active_post_id);
120 }
121 }
122
123 function refetch_callback() {
124
125 if (xmlhttp_rpc.readyState == 4) {
126 notify("All feeds updated");
127 var container = document.getElementById('feeds');
128 container.innerHTML = xmlhttp_rpc.responseText;
129 document.title = "Tiny Tiny RSS";
130 }
131 }
132
133 function scheduleFeedUpdate(force) {
134
135 notify("Updating feeds in background...");
136
137 document.title = "Tiny Tiny RSS - Updating...";
138
139 var query_str = "backend.php?op=rpc&subop=";
140
141 if (force) {
142 query_str = query_str + "forceUpdateAllFeeds";
143 } else {
144 query_str = query_str + "updateAllFeeds";
145 }
146
147 if (xmlhttp_ready(xmlhttp_rpc)) {
148 xmlhttp_rpc.open("GET", query_str, true);
149 xmlhttp_rpc.onreadystatechange=refetch_callback;
150 xmlhttp_rpc.send(null);
151 } else {
152 printLockingError();
153 }
154 }
155
156 function updateFeedList(silent, fetch) {
157
158 if (silent != true) {
159 notify("Loading feed list...");
160 }
161
162 var query_str = "backend.php?op=feeds";
163
164 if (fetch) query_str = query_str + "&fetch=yes";
165
166 if (xmlhttp_ready(xmlhttp)) {
167 xmlhttp.open("GET", query_str, true);
168 xmlhttp.onreadystatechange=feedlist_callback;
169 xmlhttp.send(null);
170 } else {
171 printLockingError();
172 }
173 }
174
175 function catchupPage(feed) {
176
177 if (!xmlhttp_ready(xmlhttp)) {
178 printLockingError();
179 return
180 }
181
182 var content = document.getElementById("headlinesList");
183
184 var rows = new Array();
185
186 for (i = 0; i < content.rows.length; i++) {
187 var row_id = content.rows[i].id.replace("RROW-", "");
188 if (row_id.length > 0) {
189 if (content.rows[i].className.match("Unread")) {
190 rows.push(row_id);
191 content.rows[i].className = content.rows[i].className.replace("Unread", "");
192 }
193 }
194 }
195
196 if (rows.length > 0) {
197
198 var feedr = document.getElementById("FEEDR-" + feed);
199 var feedu = document.getElementById("FEEDU-" + feed);
200
201 feedu.innerHTML = feedu.innerHTML - rows.length;
202
203 if (feedu.innerHTML > 0 && !feedr.className.match("Unread")) {
204 feedr.className = feedr.className + "Unread";
205 } else if (feedu.innerHTML <= 0) {
206 feedr.className = feedr.className.replace("Unread", "");
207 }
208
209 var query_str = "backend.php?op=rpc&subop=catchupPage&ids=" +
210 param_escape(rows.toString());
211
212 notify("Marking this page as read...");
213
214 var button = document.getElementById("btnCatchupPage");
215
216 button.className = "disabledButton";
217 button.href = "";
218
219 xmlhttp.open("GET", query_str, true);
220 xmlhttp.onreadystatechange=notify_callback;
221 xmlhttp.send(null);
222
223 } else {
224 notify("No unread items on this page.");
225
226 }
227 }
228
229 function catchupAllFeeds() {
230
231 if (!xmlhttp_ready(xmlhttp)) {
232 printLockingError();
233 return
234 }
235 var query_str = "backend.php?op=feeds&subop=catchupAll";
236
237 notify("Marking all feeds as read...");
238
239 xmlhttp.open("GET", query_str, true);
240 xmlhttp.onreadystatechange=feedlist_callback;
241 xmlhttp.send(null);
242
243 }
244
245 function viewfeed(feed, skip, subop) {
246
247 enableHotkeys();
248
249 var searchbox = document.getElementById("searchbox");
250
251 if (searchbox) {
252 search_query = searchbox.value;
253 } else {
254 search_query = "";
255 }
256
257 /* if (active_feed_id == feed && subop != "ForceUpdate") {
258 notify("This feed is currently selected.");
259 return;
260 } */
261
262 if (skip < 0 || skip > total_feed_entries) {
263 return;
264 }
265
266 if (!xmlhttp_ready(xmlhttp)) {
267 printLockingError();
268 return
269 }
270
271 if (active_feed_id != feed || skip != active_offset) {
272 active_post_id = false;
273 }
274
275 active_feed_id = feed;
276 active_offset = skip;
277
278 var query = "backend.php?op=viewfeed&feed=" + param_escape(feed) +
279 "&skip=" + param_escape(skip) + "&subop=" + param_escape(subop);
280
281 if (search_query != "") {
282 query = query + "&search=" + param_escape(search_query);
283 }
284
285 xmlhttp.open("GET", query, true);
286 xmlhttp.onreadystatechange=viewfeed_callback;
287 xmlhttp.send(null);
288
289 notify("Loading headlines...");
290
291 }
292
293 function markHeadline(id) {
294 var row = document.getElementById("RROW-" + id);
295 if (row) {
296 row.className = row.className + "Selected";
297 }
298 }
299
300 function cleanSelected(element) {
301 var content = document.getElementById(element);
302
303 var rows = new Array();
304
305 for (i = 0; i < content.rows.length; i++) {
306 content.rows[i].className = content.rows[i].className.replace("Selected", "");
307 }
308
309 }
310
311 function view(id,feed_id) {
312
313 enableHotkeys();
314
315 if (!xmlhttp_ready(xmlhttp_view)) {
316 printLockingError();
317 return
318 }
319
320 var crow = document.getElementById("RROW-" + id);
321
322 if (crow.className.match("Unread")) {
323 var umark = document.getElementById("FEEDU-" + feed_id);
324 umark.innerHTML = umark.innerHTML - 1;
325 crow.className = crow.className.replace("Unread", "");
326
327 if (umark.innerHTML == "0") {
328 var feedr = document.getElementById("FEEDR-" + feed_id);
329 feedr.className = feedr.className.replace("Unread", "");
330 }
331
332 total_unread--;
333 }
334
335 cleanSelected("headlinesList");
336 // crow.className = crow.className + "Selected";
337
338 var upd_img_pic = document.getElementById("FUPDPIC-" + id);
339
340 if (upd_img_pic) {
341 upd_img_pic.innerHTML = "";
342 }
343
344 // document.getElementById('content').innerHTML='Loading, please wait...';
345
346 active_post_id = id;
347
348 xmlhttp_view.open("GET", "backend.php?op=view&id=" + param_escape(id), true);
349 xmlhttp_view.onreadystatechange=view_callback;
350 xmlhttp_view.send(null);
351
352
353 }
354
355 function timeout() {
356 scheduleFeedUpdate(true);
357 setTimeout("timeout()", 1800*1000);
358 }
359
360 function resetSearch() {
361 document.getElementById("searchbox").value = "";
362 viewfeed(active_feed_id, 0, "");
363 }
364
365 function search(feed) {
366 viewfeed(feed, 0, "");
367 }
368
369 function localPiggieFunction(enable) {
370 if (enable) {
371 var query_str = "backend.php?op=feeds&subop=piggie";
372
373 if (xmlhttp_ready(xmlhttp)) {
374
375 xmlhttp.open("GET", query_str, true);
376 xmlhttp.onreadystatechange=feedlist_callback;
377 xmlhttp.send(null);
378 }
379 }
380 }
381
382 function relativeid_callback() {
383
384 if (xmlhttp_rpc.readyState == 4) {
385 notify(xmlhttp_rpc.responseText);
386 }
387
388 }
389
390 function getVisibleHeadlineIds() {
391
392 var content = document.getElementById("headlinesList");
393
394 var rows = new Array();
395
396 for (i = 0; i < content.rows.length; i++) {
397 var row_id = content.rows[i].id.replace("RROW-", "");
398 if (row_id.length > 0) {
399 rows.push(row_id);
400 }
401 }
402 return rows;
403 }
404
405 function getFirstVisibleHeadlineId() {
406 var rows = getVisibleHeadlineIds();
407 return rows[0];
408 }
409
410 function getLastVisibleHeadlineId() {
411 var rows = getVisibleHeadlineIds();
412 return rows[rows.length-1];
413 }
414
415 function moveToPost(mode) {
416
417 var rows = getVisibleHeadlineIds();
418
419 var prev_id;
420 var next_id;
421
422 if (active_post_id == false) {
423 next_id = getFirstVisibleHeadlineId();
424 prev_id = getLastVisibleHeadlineId();
425 } else {
426 for (var i = 0; i < rows.length; i++) {
427 if (rows[i] == active_post_id) {
428 prev_id = rows[i-1];
429 next_id = rows[i+1];
430 }
431 }
432 }
433
434 if (mode == "next") {
435 if (next_id != undefined) {
436 view(next_id, active_feed_id);
437 } else {
438 _viewfeed_autoselect_first = true;
439 viewfeed(active_feed_id, active_offset+15);
440 }
441 }
442
443 if (mode == "prev") {
444 if ( prev_id != undefined) {
445 view(prev_id, active_feed_id);
446 } else {
447 _viewfeed_autoselect_last = true;
448 viewfeed(active_feed_id, active_offset-15);
449 }
450 }
451
452 }
453
454 function localHotkeyHandler(keycode) {
455
456 if (keycode == 78) {
457 return moveToPost('next');
458 }
459
460 if (keycode == 80) {
461 return moveToPost('prev');
462 }
463
464 if (keycode == 82) {
465 return scheduleFeedUpdate(true);
466 }
467
468 if (keycode == 85) {
469 return viewfeed(active_feed_id, active_offset, "ForceUpdate");
470 }
471
472 // notify("KC: " + keycode);
473
474 }
475
476
477 function init() {
478
479 // IE kludge
480
481 if (xmlhttp && !xmlhttp_rpc) {
482 xmlhttp_rpc = xmlhttp;
483 xmlhttp_view = xmlhttp;
484 }
485
486 if (!xmlhttp || !xmlhttp_rpc || !xmlhttp_view) {
487 document.getElementById("headlines").innerHTML =
488 "<b>Fatal error:</b> This program needs XmlHttpRequest " +
489 "to function properly. Your browser doesn't seem to support it.";
490 return;
491 }
492
493 updateFeedList(false, false);
494 document.onkeydown = hotkey_handler;
495 setTimeout("timeout()", 1800*1000);
496 }