viewfeed.js 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231
  1. var active_post_id = false;
  2. var article_cache = new Array();
  3. var vgroup_last_feed = false;
  4. var post_under_pointer = false;
  5. var last_requested_article = false;
  6. var catchup_id_batch = [];
  7. var catchup_timeout_id = false;
  8. var feed_precache_timeout_id = false;
  9. var precache_idle_timeout_id = false;
  10. var cids_requested = [];
  11. var has_storage = 'sessionStorage' in window && window['sessionStorage'] !== null;
  12. function headlines_callback2(transport, offset, background, infscroll_req) {
  13. try {
  14. handle_rpc_json(transport);
  15. loading_set_progress(25);
  16. console.log("headlines_callback2 [offset=" + offset + "] B:" + background + " I:" + infscroll_req);
  17. var is_cat = false;
  18. var feed_id = false;
  19. var reply = false;
  20. try {
  21. reply = JSON.parse(transport.responseText);
  22. } catch (e) {
  23. console.error(e);
  24. }
  25. if (reply) {
  26. is_cat = reply['headlines']['is_cat'];
  27. feed_id = reply['headlines']['id'];
  28. if (background) {
  29. var content = reply['headlines']['content'];
  30. if (getInitParam("cdm_auto_catchup") == 1) {
  31. content = content + "<div id='headlines-spacer'></div>";
  32. }
  33. cache_headlines(feed_id, is_cat, reply['headlines']['toolbar'], content);
  34. return;
  35. }
  36. setActiveFeedId(feed_id, is_cat);
  37. try {
  38. if (offset == 0 && infscroll_req == false) {
  39. $("headlines-frame").scrollTop = 0;
  40. }
  41. } catch (e) { };
  42. var headlines_count = reply['headlines-info']['count'];
  43. vgroup_last_feed = reply['headlines-info']['vgroup_last_feed'];
  44. if (parseInt(headlines_count) < getInitParam("default_article_limit")) {
  45. _infscroll_disable = 1;
  46. } else {
  47. _infscroll_disable = 0;
  48. }
  49. var counters = reply['counters'];
  50. var articles = reply['articles'];
  51. //var runtime_info = reply['runtime-info'];
  52. if (offset == 0 && infscroll_req == false) {
  53. dijit.byId("headlines-frame").attr('content',
  54. reply['headlines']['content']);
  55. dijit.byId("headlines-toolbar").attr('content',
  56. reply['headlines']['toolbar']);
  57. if (getInitParam("cdm_auto_catchup") == 1) {
  58. var hsp = $("headlines-spacer");
  59. if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
  60. dijit.byId('headlines-frame').domNode.appendChild(hsp);
  61. }
  62. initHeadlinesMenu();
  63. } else {
  64. if (headlines_count > 0 && feed_id == getActiveFeedId() && is_cat == activeFeedIsCat()) {
  65. console.log("adding some more headlines...");
  66. var c = dijit.byId("headlines-frame");
  67. var ids = getSelectedArticleIds2();
  68. $("headlines-tmp").innerHTML = reply['headlines']['content'];
  69. var hsp = $("headlines-spacer");
  70. if (hsp)
  71. c.domNode.removeChild(hsp);
  72. $$("#headlines-tmp > div").each(function(row) {
  73. if ($$("#headlines-frame DIV[id="+row.id+"]").length == 0) {
  74. row.style.display = 'none';
  75. c.domNode.appendChild(row);
  76. } else {
  77. row.parentNode.removeChild(row);
  78. }
  79. });
  80. if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
  81. fixHeadlinesOrder(getLoadedArticleIds());
  82. if (getInitParam("cdm_auto_catchup") == 1) {
  83. c.domNode.appendChild(hsp);
  84. }
  85. console.log("restore selected ids: " + ids);
  86. for (var i = 0; i < ids.length; i++) {
  87. markHeadline(ids[i]);
  88. }
  89. initHeadlinesMenu();
  90. $$("#headlines-frame > div[id*=RROW]").each(
  91. function(child) {
  92. if (!Element.visible(child))
  93. new Effect.Appear(child, { duration : 0.5 });
  94. });
  95. } else {
  96. console.log("no new headlines received");
  97. var hsp = $("headlines-spacer");
  98. if (hsp) hsp.innerHTML = "";
  99. }
  100. }
  101. if (headlines_count > 0)
  102. cache_headlines(feed_id, is_cat, reply['headlines']['toolbar'], $("headlines-frame").innerHTML);
  103. if (articles) {
  104. for (var i = 0; i < articles.length; i++) {
  105. var a_id = articles[i]['id'];
  106. cache_set("article:" + a_id, articles[i]['content']);
  107. }
  108. } else {
  109. console.log("no cached articles received");
  110. }
  111. // do not precache stuff after fresh feed
  112. if (feed_id != -3)
  113. precache_headlines();
  114. if (counters)
  115. parse_counters(counters);
  116. else
  117. request_counters();
  118. } else {
  119. console.error("Invalid object received: " + transport.responseText);
  120. dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
  121. __('Could not update headlines (invalid object received - see error console for details)') +
  122. "</div>");
  123. }
  124. _infscroll_request_sent = 0;
  125. notify("");
  126. } catch (e) {
  127. exception_error("headlines_callback2", e, transport);
  128. }
  129. }
  130. function render_article(article) {
  131. try {
  132. dijit.byId("headlines-wrap-inner").addChild(
  133. dijit.byId("content-insert"));
  134. var c = dijit.byId("content-insert");
  135. try {
  136. c.domNode.scrollTop = 0;
  137. } catch (e) { };
  138. c.attr('content', article);
  139. correctHeadlinesOffset(getActiveArticleId());
  140. try {
  141. c.focus();
  142. } catch (e) { };
  143. } catch (e) {
  144. exception_error("render_article", e);
  145. }
  146. }
  147. function showArticleInHeadlines(id) {
  148. try {
  149. selectArticles("none");
  150. var crow = $("RROW-" + id);
  151. if (!crow) return;
  152. var article_is_unread = crow.hasClassName("Unread");
  153. crow.removeClassName("Unread");
  154. selectArticles('none');
  155. var upd_img_pic = $("FUPDPIC-" + id);
  156. var view_mode = false;
  157. try {
  158. view_mode = document.forms['main_toolbar_form'].view_mode;
  159. view_mode = view_mode[view_mode.selectedIndex].value;
  160. } catch (e) {
  161. //
  162. }
  163. if (upd_img_pic && (upd_img_pic.src.match("updated.png") ||
  164. upd_img_pic.src.match("fresh_sign.png"))) {
  165. upd_img_pic.src = "images/blank_icon.gif";
  166. cache_headlines(getActiveFeedId(), activeFeedIsCat(), null, $("headlines-frame").innerHTML);
  167. } else if (article_is_unread && view_mode == "all_articles") {
  168. cache_headlines(getActiveFeedId(), activeFeedIsCat(), null, $("headlines-frame").innerHTML);
  169. }
  170. markHeadline(id);
  171. if (article_is_unread)
  172. _force_scheduled_update = true;
  173. } catch (e) {
  174. exception_error("showArticleInHeadlines", e);
  175. }
  176. }
  177. function article_callback2(transport, id) {
  178. try {
  179. console.log("article_callback2 " + id);
  180. handle_rpc_json(transport);
  181. var reply = false;
  182. try {
  183. reply = JSON.parse(transport.responseText);
  184. } catch (e) {
  185. console.error(e);
  186. }
  187. if (reply) {
  188. var upic = $('FUPDPIC-' + id);
  189. if (upic) upic.src = 'images/blank_icon.gif';
  190. reply.each(function(article) {
  191. if (active_post_id == article['id']) {
  192. render_article(article['content']);
  193. }
  194. cids_requested.remove(article['id']);
  195. cache_set("article:" + article['id'], article['content']);
  196. });
  197. // if (id != last_requested_article) {
  198. // console.log("requested article id is out of sequence, aborting");
  199. // return;
  200. // }
  201. } else {
  202. console.error("Invalid object received: " + transport.responseText);
  203. render_article("<div class='whiteBox'>" +
  204. __('Could not display article (invalid object received - see error console for details)') + "</div>");
  205. }
  206. request_counters();
  207. try {
  208. if (!_infscroll_disable &&
  209. $$("#headlines-frame > div[id*=RROW]").last().hasClassName("Selected")) {
  210. loadMoreHeadlines();
  211. }
  212. } catch (e) {
  213. console.warn(e);
  214. }
  215. notify("");
  216. } catch (e) {
  217. exception_error("article_callback2", e, transport);
  218. }
  219. }
  220. function view(id) {
  221. try {
  222. console.log("loading article: " + id);
  223. var cached_article = cache_get("article:" + id);
  224. console.log("cache check result: " + (cached_article != false));
  225. hideAuxDlg();
  226. var query = "?op=view&id=" + param_escape(id);
  227. var neighbor_ids = getRelativePostIds(id);
  228. /* only request uncached articles */
  229. var cids_to_request = [];
  230. for (var i = 0; i < neighbor_ids.length; i++) {
  231. if (cids_requested.indexOf(neighbor_ids[i]) == -1)
  232. if (!cache_get("article:" + neighbor_ids[i])) {
  233. cids_to_request.push(neighbor_ids[i]);
  234. cids_requested.push(neighbor_ids[i]);
  235. }
  236. }
  237. console.log("additional ids: " + cids_to_request.toString());
  238. query = query + "&cids=" + cids_to_request.toString();
  239. var crow = $("RROW-" + id);
  240. var article_is_unread = crow.hasClassName("Unread");
  241. active_post_id = id;
  242. showArticleInHeadlines(id);
  243. precache_headlines();
  244. if (!cached_article) {
  245. var upic = $('FUPDPIC-' + id);
  246. if (upic) {
  247. upic.src = getInitParam("sign_progress");
  248. }
  249. } else if (cached_article && article_is_unread) {
  250. query = query + "&mode=prefetch";
  251. render_article(cached_article);
  252. } else if (cached_article) {
  253. query = query + "&mode=prefetch_old";
  254. render_article(cached_article);
  255. // if we don't need to request any relative ids, we might as well skip
  256. // the server roundtrip altogether
  257. if (cids_to_request.length == 0) {
  258. try {
  259. if (!_infscroll_disable &&
  260. $$("#headlines-frame > div[id*=RROW]").last().hasClassName("Selected")) {
  261. loadMoreHeadlines();
  262. }
  263. } catch (e) {
  264. console.warn(e);
  265. }
  266. return;
  267. }
  268. }
  269. last_requested_article = id;
  270. console.log(query);
  271. new Ajax.Request("backend.php", {
  272. parameters: query,
  273. onComplete: function(transport) {
  274. article_callback2(transport, id);
  275. } });
  276. return false;
  277. } catch (e) {
  278. exception_error("view", e);
  279. }
  280. }
  281. function toggleMark(id, client_only) {
  282. try {
  283. var query = "?op=rpc&id=" + id + "&subop=mark";
  284. var img = $("FMPIC-" + id);
  285. if (!img) return;
  286. if (img.src.match("mark_unset")) {
  287. img.src = img.src.replace("mark_unset", "mark_set");
  288. img.alt = __("Unstar article");
  289. query = query + "&mark=1";
  290. } else {
  291. img.src = img.src.replace("mark_set", "mark_unset");
  292. img.alt = __("Star article");
  293. query = query + "&mark=0";
  294. }
  295. cache_headlines(getActiveFeedId(), activeFeedIsCat(), null, $("headlines-frame").innerHTML);
  296. if (!client_only) {
  297. new Ajax.Request("backend.php", {
  298. parameters: query,
  299. onComplete: function(transport) {
  300. handle_rpc_json(transport);
  301. } });
  302. }
  303. } catch (e) {
  304. exception_error("toggleMark", e);
  305. }
  306. }
  307. function togglePub(id, client_only, no_effects, note) {
  308. try {
  309. var query = "?op=rpc&id=" + id + "&subop=publ";
  310. if (note != undefined) {
  311. query = query + "&note=" + param_escape(note);
  312. } else {
  313. query = query + "&note=undefined";
  314. }
  315. var img = $("FPPIC-" + id);
  316. if (!img) return;
  317. if (img.src.match("pub_unset") || note != undefined) {
  318. img.src = img.src.replace("pub_unset", "pub_set");
  319. img.alt = __("Unpublish article");
  320. query = query + "&pub=1";
  321. } else {
  322. img.src = img.src.replace("pub_set", "pub_unset");
  323. img.alt = __("Publish article");
  324. query = query + "&pub=0";
  325. }
  326. cache_headlines(getActiveFeedId(), activeFeedIsCat(), null, $("headlines-frame").innerHTML);
  327. if (!client_only) {
  328. new Ajax.Request("backend.php", {
  329. parameters: query,
  330. onComplete: function(transport) {
  331. handle_rpc_json(transport);
  332. } });
  333. }
  334. } catch (e) {
  335. exception_error("togglePub", e);
  336. }
  337. }
  338. function moveToPost(mode) {
  339. try {
  340. var rows = getVisibleArticleIds();
  341. var prev_id = false;
  342. var next_id = false;
  343. if (!$('RROW-' + active_post_id)) {
  344. active_post_id = false;
  345. }
  346. if (active_post_id == false) {
  347. next_id = getFirstVisibleHeadlineId();
  348. prev_id = getLastVisibleHeadlineId();
  349. } else {
  350. for (var i = 0; i < rows.length; i++) {
  351. if (rows[i] == active_post_id) {
  352. prev_id = rows[i-1];
  353. next_id = rows[i+1];
  354. }
  355. }
  356. }
  357. if (mode == "next") {
  358. if (next_id) {
  359. if (isCdmMode()) {
  360. cdmExpandArticle(next_id);
  361. cdmScrollToArticleId(next_id);
  362. } else {
  363. correctHeadlinesOffset(next_id);
  364. view(next_id, getActiveFeedId());
  365. }
  366. }
  367. }
  368. if (mode == "prev") {
  369. if (prev_id) {
  370. if (isCdmMode()) {
  371. cdmExpandArticle(prev_id);
  372. cdmScrollToArticleId(prev_id);
  373. } else {
  374. correctHeadlinesOffset(prev_id);
  375. view(prev_id, getActiveFeedId());
  376. }
  377. }
  378. }
  379. } catch (e) {
  380. exception_error("moveToPost", e);
  381. }
  382. }
  383. function toggleSelected(id, force_on) {
  384. try {
  385. var cb = $("RCHK-" + id);
  386. var row = $("RROW-" + id);
  387. if (row) {
  388. if (row.hasClassName('Selected') && !force_on) {
  389. row.removeClassName('Selected');
  390. if (cb) cb.checked = false;
  391. } else {
  392. row.addClassName('Selected');
  393. if (cb) cb.checked = true;
  394. }
  395. }
  396. } catch (e) {
  397. exception_error("toggleSelected", e);
  398. }
  399. }
  400. function toggleUnread_afh(effect) {
  401. try {
  402. var elem = effect.element;
  403. elem.style.backgroundColor = "";
  404. } catch (e) {
  405. exception_error("toggleUnread_afh", e);
  406. }
  407. }
  408. function toggleUnread(id, cmode, effect) {
  409. try {
  410. var row = $("RROW-" + id);
  411. if (row) {
  412. if (cmode == undefined || cmode == 2) {
  413. if (row.hasClassName("Unread")) {
  414. row.removeClassName("Unread");
  415. if (effect) {
  416. new Effect.Highlight(row, {duration: 1, startcolor: "#fff7d5",
  417. afterFinish: toggleUnread_afh,
  418. queue: { position:'end', scope: 'TMRQ-' + id, limit: 1 } } );
  419. }
  420. } else {
  421. row.addClassName("Unread");
  422. }
  423. } else if (cmode == 0) {
  424. row.removeClassName("Unread");
  425. if (effect) {
  426. new Effect.Highlight(row, {duration: 1, startcolor: "#fff7d5",
  427. afterFinish: toggleUnread_afh,
  428. queue: { position:'end', scope: 'TMRQ-' + id, limit: 1 } } );
  429. }
  430. } else if (cmode == 1) {
  431. row.addClassName("Unread");
  432. }
  433. if (cmode == undefined) cmode = 2;
  434. var query = "?op=rpc&subop=catchupSelected" +
  435. "&cmode=" + param_escape(cmode) + "&ids=" + param_escape(id);
  436. // notify_progress("Loading, please wait...");
  437. new Ajax.Request("backend.php", {
  438. parameters: query,
  439. onComplete: function(transport) {
  440. handle_rpc_json(transport);
  441. } });
  442. }
  443. } catch (e) {
  444. exception_error("toggleUnread", e);
  445. }
  446. }
  447. function selectionRemoveLabel(id, ids) {
  448. try {
  449. if (!ids) ids = getSelectedArticleIds2();
  450. if (ids.length == 0) {
  451. alert(__("No articles are selected."));
  452. return;
  453. }
  454. var query = "?op=rpc&subop=removeFromLabel&ids=" +
  455. param_escape(ids.toString()) + "&lid=" + param_escape(id);
  456. console.log(query);
  457. new Ajax.Request("backend.php", {
  458. parameters: query,
  459. onComplete: function(transport) {
  460. handle_rpc_json(transport);
  461. show_labels_in_headlines(transport);
  462. } });
  463. } catch (e) {
  464. exception_error("selectionAssignLabel", e);
  465. }
  466. }
  467. function selectionAssignLabel(id, ids) {
  468. try {
  469. if (!ids) ids = getSelectedArticleIds2();
  470. if (ids.length == 0) {
  471. alert(__("No articles are selected."));
  472. return;
  473. }
  474. var query = "?op=rpc&subop=assignToLabel&ids=" +
  475. param_escape(ids.toString()) + "&lid=" + param_escape(id);
  476. console.log(query);
  477. new Ajax.Request("backend.php", {
  478. parameters: query,
  479. onComplete: function(transport) {
  480. handle_rpc_json(transport);
  481. show_labels_in_headlines(transport);
  482. } });
  483. } catch (e) {
  484. exception_error("selectionAssignLabel", e);
  485. }
  486. }
  487. function selectionToggleUnread(set_state, callback, no_error) {
  488. try {
  489. var rows = getSelectedArticleIds2();
  490. if (rows.length == 0 && !no_error) {
  491. alert(__("No articles are selected."));
  492. return;
  493. }
  494. for (var i = 0; i < rows.length; i++) {
  495. var row = $("RROW-" + rows[i]);
  496. if (row) {
  497. if (set_state == undefined) {
  498. if (row.hasClassName("Unread")) {
  499. row.removeClassName("Unread");
  500. } else {
  501. row.addClassName("Unread");
  502. }
  503. }
  504. if (set_state == false) {
  505. row.removeClassName("Unread");
  506. }
  507. if (set_state == true) {
  508. row.addClassName("Unread");
  509. }
  510. }
  511. }
  512. if (rows.length > 0) {
  513. var cmode = "";
  514. if (set_state == undefined) {
  515. cmode = "2";
  516. } else if (set_state == true) {
  517. cmode = "1";
  518. } else if (set_state == false) {
  519. cmode = "0";
  520. }
  521. var query = "?op=rpc&subop=catchupSelected" +
  522. "&cmode=" + cmode + "&ids=" + param_escape(rows.toString());
  523. notify_progress("Loading, please wait...");
  524. new Ajax.Request("backend.php", {
  525. parameters: query,
  526. onComplete: function(transport) {
  527. handle_rpc_json(transport);
  528. if (callback) callback(transport);
  529. } });
  530. }
  531. } catch (e) {
  532. exception_error("selectionToggleUnread", e);
  533. }
  534. }
  535. function selectionToggleMarked() {
  536. try {
  537. var rows = getSelectedArticleIds2();
  538. if (rows.length == 0) {
  539. alert(__("No articles are selected."));
  540. return;
  541. }
  542. for (var i = 0; i < rows.length; i++) {
  543. toggleMark(rows[i], true, true);
  544. }
  545. if (rows.length > 0) {
  546. var query = "?op=rpc&subop=markSelected&ids=" +
  547. param_escape(rows.toString()) + "&cmode=2";
  548. new Ajax.Request("backend.php", {
  549. parameters: query,
  550. onComplete: function(transport) {
  551. handle_rpc_json(transport);
  552. } });
  553. }
  554. } catch (e) {
  555. exception_error("selectionToggleMarked", e);
  556. }
  557. }
  558. function selectionTogglePublished() {
  559. try {
  560. var rows = getSelectedArticleIds2();
  561. if (rows.length == 0) {
  562. alert(__("No articles are selected."));
  563. return;
  564. }
  565. for (var i = 0; i < rows.length; i++) {
  566. togglePub(rows[i], true, true);
  567. }
  568. if (rows.length > 0) {
  569. var query = "?op=rpc&subop=publishSelected&ids=" +
  570. param_escape(rows.toString()) + "&cmode=2";
  571. new Ajax.Request("backend.php", {
  572. parameters: query,
  573. onComplete: function(transport) {
  574. handle_rpc_json(transport);
  575. } });
  576. }
  577. } catch (e) {
  578. exception_error("selectionToggleMarked", e);
  579. }
  580. }
  581. function getSelectedArticleIds2() {
  582. var rv = [];
  583. $$("#headlines-frame > div[id*=RROW][class*=Selected]").each(
  584. function(child) {
  585. rv.push(child.id.replace("RROW-", ""));
  586. });
  587. return rv;
  588. }
  589. function getLoadedArticleIds() {
  590. var rv = [];
  591. var children = $$("#headlines-frame > div[id*=RROW-]");
  592. children.each(function(child) {
  593. rv.push(child.id.replace("RROW-", ""));
  594. });
  595. return rv;
  596. }
  597. // mode = all,none,unread,invert
  598. function selectArticles(mode) {
  599. try {
  600. var children = $$("#headlines-frame > div[id*=RROW]");
  601. children.each(function(child) {
  602. var id = child.id.replace("RROW-", "");
  603. var cb = $("RCHK-" + id);
  604. if (mode == "all") {
  605. child.addClassName("Selected");
  606. cb.checked = true;
  607. } else if (mode == "unread") {
  608. if (child.hasClassName("Unread")) {
  609. child.addClassName("Selected");
  610. cb.checked = true;
  611. } else {
  612. child.removeClassName("Selected");
  613. cb.checked = false;
  614. }
  615. } else if (mode == "invert") {
  616. if (child.hasClassName("Selected")) {
  617. child.removeClassName("Selected");
  618. cb.checked = false;
  619. } else {
  620. child.addClassName("Selected");
  621. cb.checked = true;
  622. }
  623. } else {
  624. child.removeClassName("Selected");
  625. cb.checked = false;
  626. }
  627. });
  628. } catch (e) {
  629. exception_error("selectArticles", e);
  630. }
  631. }
  632. function catchupPage() {
  633. var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
  634. var str = __("Mark all visible articles in %s as read?");
  635. str = str.replace("%s", fn);
  636. if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
  637. return;
  638. }
  639. selectArticles('all');
  640. selectionToggleUnread(false, 'viewCurrentFeed()', true);
  641. selectArticles('none');
  642. }
  643. function deleteSelection() {
  644. try {
  645. var rows = getSelectedArticleIds2();
  646. if (rows.length == 0) {
  647. alert(__("No articles are selected."));
  648. return;
  649. }
  650. var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
  651. var str;
  652. if (getActiveFeedId() != 0) {
  653. str = __("Delete %d selected articles in %s?");
  654. } else {
  655. str = __("Delete %d selected articles?");
  656. }
  657. str = str.replace("%d", rows.length);
  658. str = str.replace("%s", fn);
  659. if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
  660. return;
  661. }
  662. query = "?op=rpc&subop=delete&ids=" + param_escape(rows);
  663. console.log(query);
  664. new Ajax.Request("backend.php", {
  665. parameters: query,
  666. onComplete: function(transport) {
  667. handle_rpc_json(transport);
  668. viewCurrentFeed();
  669. } });
  670. } catch (e) {
  671. exception_error("deleteSelection", e);
  672. }
  673. }
  674. function archiveSelection() {
  675. try {
  676. var rows = getSelectedArticleIds2();
  677. if (rows.length == 0) {
  678. alert(__("No articles are selected."));
  679. return;
  680. }
  681. var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
  682. var str;
  683. var op;
  684. if (getActiveFeedId() != 0) {
  685. str = __("Archive %d selected articles in %s?");
  686. op = "archive";
  687. } else {
  688. str = __("Move %d archived articles back?");
  689. op = "unarchive";
  690. }
  691. str = str.replace("%d", rows.length);
  692. str = str.replace("%s", fn);
  693. if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
  694. return;
  695. }
  696. query = "?op=rpc&subop="+op+"&ids=" + param_escape(rows);
  697. console.log(query);
  698. for (var i = 0; i < rows.length; i++) {
  699. cache_delete("article:" + rows[i]);
  700. }
  701. new Ajax.Request("backend.php", {
  702. parameters: query,
  703. onComplete: function(transport) {
  704. handle_rpc_json(transport);
  705. viewCurrentFeed();
  706. } });
  707. } catch (e) {
  708. exception_error("archiveSelection", e);
  709. }
  710. }
  711. function catchupSelection() {
  712. try {
  713. var rows = getSelectedArticleIds2();
  714. if (rows.length == 0) {
  715. alert(__("No articles are selected."));
  716. return;
  717. }
  718. var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
  719. var str = __("Mark %d selected articles in %s as read?");
  720. str = str.replace("%d", rows.length);
  721. str = str.replace("%s", fn);
  722. if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
  723. return;
  724. }
  725. selectionToggleUnread(false, 'viewCurrentFeed()', true);
  726. } catch (e) {
  727. exception_error("catchupSelection", e);
  728. }
  729. }
  730. function editArticleTags(id) {
  731. var query = "backend.php?op=dlg&id=editArticleTags&param=" + param_escape(id);
  732. if (dijit.byId("editTagsDlg"))
  733. dijit.byId("editTagsDlg").destroyRecursive();
  734. dialog = new dijit.Dialog({
  735. id: "editTagsDlg",
  736. title: __("Edit article Tags"),
  737. style: "width: 600px",
  738. execute: function() {
  739. if (this.validate()) {
  740. var query = dojo.objectToQuery(this.attr('value'));
  741. notify_progress("Saving article tags...", true);
  742. new Ajax.Request("backend.php", {
  743. parameters: query,
  744. onComplete: function(transport) {
  745. notify('');
  746. dialog.hide();
  747. var data = JSON.parse(transport.responseText);
  748. if (data) {
  749. var tags_str = article.tags;
  750. var id = tags_str.id;
  751. var tags = $("ATSTR-" + id);
  752. var tooltip = dijit.byId("ATSTRTIP-" + id);
  753. if (tags) tags.innerHTML = tags_str.content;
  754. if (tooltip) tooltip.attr('label', tags_str.content_full);
  755. cache_delete("article:" + id);
  756. }
  757. }});
  758. }
  759. },
  760. href: query,
  761. });
  762. var tmph = dojo.connect(dialog, 'onLoad', function() {
  763. dojo.disconnect(tmph);
  764. new Ajax.Autocompleter('tags_str', 'tags_choices',
  765. "backend.php?op=rpc&subop=completeTags",
  766. { tokens: ',', paramName: "search" });
  767. });
  768. dialog.show();
  769. }
  770. function cdmScrollToArticleId(id) {
  771. try {
  772. var ctr = $("headlines-frame");
  773. var e = $("RROW-" + id);
  774. if (!e || !ctr) return;
  775. ctr.scrollTop = e.offsetTop;
  776. } catch (e) {
  777. exception_error("cdmScrollToArticleId", e);
  778. }
  779. }
  780. function getActiveArticleId() {
  781. return active_post_id;
  782. }
  783. function postMouseIn(id) {
  784. post_under_pointer = id;
  785. }
  786. function postMouseOut(id) {
  787. post_under_pointer = false;
  788. }
  789. function headlines_scroll_handler(e) {
  790. try {
  791. var hsp = $("headlines-spacer");
  792. if (!_infscroll_disable) {
  793. if (hsp && (e.scrollTop + e.offsetHeight > hsp.offsetTop) ||
  794. e.scrollTop + e.offsetHeight > e.scrollHeight - 100) {
  795. if (hsp)
  796. hsp.innerHTML = "<img src='images/indicator_tiny.gif'> " +
  797. __("Loading, please wait...");
  798. loadMoreHeadlines();
  799. return;
  800. }
  801. } else {
  802. if (hsp) hsp.innerHTML = "";
  803. }
  804. if (getInitParam("cdm_auto_catchup") == 1) {
  805. $$("#headlines-frame > div[id*=RROW][class*=Unread]").each(
  806. function(child) {
  807. if ($("headlines-frame").scrollTop >
  808. (child.offsetTop + child.offsetHeight/2)) {
  809. var id = child.id.replace("RROW-", "");
  810. if (catchup_id_batch.indexOf(id) == -1)
  811. catchup_id_batch.push(id);
  812. //console.log("auto_catchup_batch: " + catchup_id_batch.toString());
  813. }
  814. });
  815. if (catchup_id_batch.length > 0) {
  816. window.clearTimeout(catchup_timeout_id);
  817. if (!_infscroll_request_sent) {
  818. catchup_timeout_id = window.setTimeout('catchupBatchedArticles()',
  819. 2000);
  820. }
  821. }
  822. }
  823. } catch (e) {
  824. console.warn("headlines_scroll_handler: " + e);
  825. }
  826. }
  827. function catchupBatchedArticles() {
  828. try {
  829. if (catchup_id_batch.length > 0 && !_infscroll_request_sent) {
  830. var query = "?op=rpc&subop=catchupSelected" +
  831. "&cmode=0&ids=" + param_escape(catchup_id_batch.toString());
  832. new Ajax.Request("backend.php", {
  833. parameters: query,
  834. onComplete: function(transport) {
  835. handle_rpc_json(transport);
  836. catchup_id_batch.each(function(id) {
  837. var elem = $("RROW-" + id);
  838. if (elem) elem.removeClassName("Unread");
  839. });
  840. catchup_id_batch = [];
  841. } });
  842. }
  843. } catch (e) {
  844. exception_error("catchupBatchedArticles", e);
  845. }
  846. }
  847. function catchupRelativeToArticle(below) {
  848. try {
  849. if (!getActiveArticleId()) {
  850. alert(__("No article is selected."));
  851. return;
  852. }
  853. var visible_ids = getVisibleArticleIds();
  854. var ids_to_mark = new Array();
  855. if (!below) {
  856. for (var i = 0; i < visible_ids.length; i++) {
  857. if (visible_ids[i] != getActiveArticleId()) {
  858. var e = $("RROW-" + visible_ids[i]);
  859. if (e && e.hasClassName("Unread")) {
  860. ids_to_mark.push(visible_ids[i]);
  861. }
  862. } else {
  863. break;
  864. }
  865. }
  866. } else {
  867. for (var i = visible_ids.length-1; i >= 0; i--) {
  868. if (visible_ids[i] != getActiveArticleId()) {
  869. var e = $("RROW-" + visible_ids[i]);
  870. if (e && e.hasClassName("Unread")) {
  871. ids_to_mark.push(visible_ids[i]);
  872. }
  873. } else {
  874. break;
  875. }
  876. }
  877. }
  878. if (ids_to_mark.length == 0) {
  879. alert(__("No articles found to mark"));
  880. } else {
  881. var msg = __("Mark %d article(s) as read?").replace("%d", ids_to_mark.length);
  882. if (getInitParam("confirm_feed_catchup") != 1 || confirm(msg)) {
  883. for (var i = 0; i < ids_to_mark.length; i++) {
  884. var e = $("RROW-" + ids_to_mark[i]);
  885. e.removeClassName("Unread");
  886. }
  887. var query = "?op=rpc&subop=catchupSelected" +
  888. "&cmode=0" + "&ids=" + param_escape(ids_to_mark.toString());
  889. new Ajax.Request("backend.php", {
  890. parameters: query,
  891. onComplete: function(transport) {
  892. handle_rpc_json(transport);
  893. } });
  894. }
  895. }
  896. } catch (e) {
  897. exception_error("catchupRelativeToArticle", e);
  898. }
  899. }
  900. function cdmExpandArticle(id) {
  901. try {
  902. hideAuxDlg();
  903. var elem = $("CICD-" + active_post_id);
  904. var upd_img_pic = $("FUPDPIC-" + id);
  905. if (upd_img_pic && (upd_img_pic.src.match("updated.png") ||
  906. upd_img_pic.src.match("fresh_sign.png"))) {
  907. upd_img_pic.src = "images/blank_icon.gif";
  908. }
  909. if (id == active_post_id && Element.visible(elem))
  910. return true;
  911. selectArticles("none");
  912. var old_offset = $("RROW-" + id).offsetTop;
  913. if (active_post_id && elem && !getInitParam("cdm_expanded")) {
  914. Element.hide(elem);
  915. Element.show("CEXC-" + active_post_id);
  916. }
  917. active_post_id = id;
  918. elem = $("CICD-" + id);
  919. if (!Element.visible(elem)) {
  920. Element.show(elem);
  921. Element.hide("CEXC-" + id);
  922. if ($("CWRAP-" + id).innerHTML == "") {
  923. $("FUPDPIC-" + id).src = "images/indicator_tiny.gif";
  924. $("CWRAP-" + id).innerHTML = "<div class=\"insensitive\">" +
  925. __("Loading, please wait...") + "</div>";
  926. var query = "?op=rpc&subop=cdmGetArticle&id=" + param_escape(id);
  927. var neighbor_ids = getRelativePostIds(id);
  928. /* only request uncached articles */
  929. var cids_to_request = [];
  930. for (var i = 0; i < neighbor_ids.length; i++) {
  931. if (cids_requested.indexOf(neighbor_ids[i]) == -1)
  932. if ($("CWRAP-" + neighbor_ids[i]).innerHTML == "") {
  933. cids_to_request.push(neighbor_ids[i]);
  934. cids_requested.push(neighbor_ids[i]);
  935. }
  936. }
  937. console.log("additional ids: " + cids_to_request.toString());
  938. query = query + "&cids=" + cids_to_request.toString();
  939. console.log(query);
  940. new Ajax.Request("backend.php", {
  941. parameters: query,
  942. onComplete: function(transport) {
  943. $("FUPDPIC-" + id).src = 'images/blank_icon.gif';
  944. handle_rpc_json(transport);
  945. var reply = JSON.parse(transport.responseText);
  946. reply.each(function(article) {
  947. $("CWRAP-" + article['id']).innerHTML = article['content'];
  948. cids_requested.remove(article['id']);
  949. });
  950. }});
  951. }
  952. }
  953. var new_offset = $("RROW-" + id).offsetTop;
  954. $("headlines-frame").scrollTop += (new_offset-old_offset);
  955. if ($("RROW-" + id).offsetTop != old_offset)
  956. $("headlines-frame").scrollTop = new_offset;
  957. toggleUnread(id, 0, true);
  958. toggleSelected(id);
  959. } catch (e) {
  960. exception_error("cdmExpandArticle", e);
  961. }
  962. return false;
  963. }
  964. function fixHeadlinesOrder(ids) {
  965. try {
  966. for (var i = 0; i < ids.length; i++) {
  967. var e = $("RROW-" + ids[i]);
  968. if (e) {
  969. if (i % 2 == 0) {
  970. e.removeClassName("even");
  971. e.addClassName("odd");
  972. } else {
  973. e.removeClassName("odd");
  974. e.addClassName("even");
  975. }
  976. }
  977. }
  978. } catch (e) {
  979. exception_error("fixHeadlinesOrder", e);
  980. }
  981. }
  982. function getArticleUnderPointer() {
  983. return post_under_pointer;
  984. }
  985. function zoomToArticle(event, id) {
  986. try {
  987. var cached_article = cache_get("article: " + id);
  988. if (dijit.byId("ATAB-" + id))
  989. if (!event || !event.shiftKey)
  990. return dijit.byId("content-tabs").selectChild(dijit.byId("ATAB-" + id));
  991. if (dijit.byId("ATSTRTIP-" + id))
  992. dijit.byId("ATSTRTIP-" + id).destroyRecursive();
  993. if (cached_article) {
  994. //closeArticlePanel();
  995. var article_pane = new dijit.layout.ContentPane({
  996. title: __("Loading...") , content: cached_article,
  997. style: 'padding : 0px;',
  998. id: 'ATAB-' + id,
  999. closable: true });
  1000. dijit.byId("content-tabs").addChild(article_pane);
  1001. if (!event || !event.shiftKey)
  1002. dijit.byId("content-tabs").selectChild(article_pane);
  1003. if ($("PTITLE-" + id))
  1004. article_pane.attr('title', $("PTITLE-" + id).innerHTML);
  1005. } else {
  1006. var query = "?op=rpc&subop=getArticles&ids=" + param_escape(id);
  1007. notify_progress("Loading, please wait...", true);
  1008. new Ajax.Request("backend.php", {
  1009. parameters: query,
  1010. onComplete: function(transport) {
  1011. notify('');
  1012. var reply = JSON.parse(transport.responseText);
  1013. if (reply) {
  1014. //closeArticlePanel();
  1015. var content = reply[0]['content'];
  1016. var article_pane = new dijit.layout.ContentPane({
  1017. title: "article-" + id , content: content,
  1018. style: 'padding : 0px;',
  1019. id: 'ATAB-' + id,
  1020. closable: true });
  1021. dijit.byId("content-tabs").addChild(article_pane);
  1022. if (!event || !event.shiftKey)
  1023. dijit.byId("content-tabs").selectChild(article_pane);
  1024. if ($("PTITLE-" + id))
  1025. article_pane.attr('title', $("PTITLE-" + id).innerHTML);
  1026. }
  1027. } });
  1028. }
  1029. } catch (e) {
  1030. exception_error("zoomToArticle", e);
  1031. }
  1032. }
  1033. function scrollArticle(offset) {
  1034. try {
  1035. if (!isCdmMode()) {
  1036. var ci = $("content-insert");
  1037. if (ci) {
  1038. ci.scrollTop += offset;
  1039. }
  1040. } else {
  1041. var hi = $("headlines-frame");
  1042. if (hi) {
  1043. hi.scrollTop += offset;
  1044. }
  1045. }
  1046. } catch (e) {
  1047. exception_error("scrollArticle", e);
  1048. }
  1049. }
  1050. function show_labels_in_headlines(transport) {
  1051. try {
  1052. var data = JSON.parse(transport.responseText);
  1053. if (data) {
  1054. data['info-for-headlines'].each(function(elem) {
  1055. var ctr = $("HLLCTR-" + elem.id);
  1056. if (ctr) ctr.innerHTML = elem.labels;
  1057. });
  1058. cache_headlines(getActiveFeedId(), activeFeedIsCat(), null, $("headlines-frame").innerHTML);
  1059. }
  1060. } catch (e) {
  1061. exception_error("show_labels_in_headlines", e);
  1062. }
  1063. }
  1064. /* function toggleHeadlineActions() {
  1065. try {
  1066. var e = $("headlineActionsBody");
  1067. var p = $("headlineActionsDrop");
  1068. if (!Element.visible(e)) {
  1069. Element.show(e);
  1070. } else {
  1071. Element.hide(e);
  1072. }
  1073. e.scrollTop = 0;
  1074. e.style.left = (p.offsetLeft + 1) + "px";
  1075. e.style.top = (p.offsetTop + p.offsetHeight + 2) + "px";
  1076. } catch (e) {
  1077. exception_error("toggleHeadlineActions", e);
  1078. }
  1079. } */
  1080. /* function publishWithNote(id, def_note) {
  1081. try {
  1082. if (!def_note) def_note = '';
  1083. var note = prompt(__("Please enter a note for this article:"), def_note);
  1084. if (note != undefined) {
  1085. togglePub(id, false, false, note);
  1086. }
  1087. } catch (e) {
  1088. exception_error("publishWithNote", e);
  1089. }
  1090. } */
  1091. function emailArticle(id) {
  1092. try {
  1093. if (!id) {
  1094. var ids = getSelectedArticleIds2();
  1095. if (ids.length == 0) {
  1096. alert(__("No articles are selected."));
  1097. return;
  1098. }
  1099. id = ids.toString();
  1100. }
  1101. if (dijit.byId("emailArticleDlg"))
  1102. dijit.byId("emailArticleDlg").destroyRecursive();
  1103. var query = "backend.php?op=dlg&id=emailArticle&param=" + param_escape(id);
  1104. dialog = new dijit.Dialog({
  1105. id: "emailArticleDlg",
  1106. title: __("Forward article by email"),
  1107. style: "width: 600px",
  1108. execute: function() {
  1109. if (this.validate()) {
  1110. new Ajax.Request("backend.php", {
  1111. parameters: dojo.objectToQuery(this.attr('value')),
  1112. onComplete: function(transport) {
  1113. var reply = JSON.parse(transport.responseText);
  1114. var error = reply['error'];
  1115. if (error) {
  1116. alert(__('Error sending email:') + ' ' + error);
  1117. } else {
  1118. notify_info('Your message has been sent.');
  1119. dialog.hide();
  1120. }
  1121. } });
  1122. }
  1123. },
  1124. href: query});
  1125. var tmph = dojo.connect(dialog, 'onLoad', function() {
  1126. dojo.disconnect(tmph);
  1127. new Ajax.Autocompleter('emailArticleDlg_destination', 'emailArticleDlg_dst_choices',
  1128. "backend.php?op=rpc&subop=completeEmails",
  1129. { tokens: '', paramName: "search" });
  1130. });
  1131. dialog.show();
  1132. /* displayDlg('emailArticle', id,
  1133. function () {
  1134. document.forms['article_email_form'].destination.focus();
  1135. new Ajax.Autocompleter('destination', 'destination_choices',
  1136. "backend.php?op=rpc&subop=completeEmails",
  1137. { tokens: '', paramName: "search" });
  1138. }); */
  1139. } catch (e) {
  1140. exception_error("emailArticle", e);
  1141. }
  1142. }
  1143. function dismissArticle(id) {
  1144. try {
  1145. var elem = $("RROW-" + id);
  1146. toggleUnread(id, 0, true);
  1147. new Effect.Fade(elem, {duration : 0.5});
  1148. active_post_id = false;
  1149. } catch (e) {
  1150. exception_error("dismissArticle", e);
  1151. }
  1152. }
  1153. function dismissSelectedArticles() {
  1154. try {
  1155. var ids = getVisibleArticleIds();
  1156. var tmp = [];
  1157. var sel = [];
  1158. for (var i = 0; i < ids.length; i++) {
  1159. var elem = $("RROW-" + ids[i]);
  1160. if (elem.className && elem.hasClassName("Selected") &&
  1161. ids[i] != active_post_id) {
  1162. new Effect.Fade(elem, {duration : 0.5});
  1163. sel.push(ids[i]);
  1164. } else {
  1165. tmp.push(ids[i]);
  1166. }
  1167. }
  1168. if (sel.length > 0)
  1169. selectionToggleUnread(false);
  1170. fixHeadlinesOrder(tmp);
  1171. } catch (e) {
  1172. exception_error("dismissSelectedArticles", e);
  1173. }
  1174. }
  1175. function dismissReadArticles() {
  1176. try {
  1177. var ids = getVisibleArticleIds();
  1178. var tmp = [];
  1179. for (var i = 0; i < ids.length; i++) {
  1180. var elem = $("RROW-" + ids[i]);
  1181. if (elem.className && !elem.hasClassName("Unread") &&
  1182. !elem.hasClassName("Selected")) {
  1183. new Effect.Fade(elem, {duration : 0.5});
  1184. } else {
  1185. tmp.push(ids[i]);
  1186. }
  1187. }
  1188. fixHeadlinesOrder(tmp);
  1189. } catch (e) {
  1190. exception_error("dismissSelectedArticles", e);
  1191. }
  1192. }
  1193. function getVisibleArticleIds() {
  1194. var ids = [];
  1195. try {
  1196. getLoadedArticleIds().each(function(id) {
  1197. var elem = $("RROW-" + id);
  1198. if (elem && Element.visible(elem))
  1199. ids.push(id);
  1200. });
  1201. } catch (e) {
  1202. exception_error("getVisibleArticleIds", e);
  1203. }
  1204. return ids;
  1205. }
  1206. function cdmClicked(event, id) {
  1207. try {
  1208. //var shift_key = event.shiftKey;
  1209. hideAuxDlg();
  1210. if (!event.ctrlKey) {
  1211. if (!getInitParam("cdm_expanded")) {
  1212. return cdmExpandArticle(id);
  1213. } else {
  1214. selectArticles("none");
  1215. toggleSelected(id);
  1216. var elem = $("RROW-" + id);
  1217. if (elem)
  1218. elem.removeClassName("Unread");
  1219. var upd_img_pic = $("FUPDPIC-" + id);
  1220. if (upd_img_pic && (upd_img_pic.src.match("updated.png") ||
  1221. upd_img_pic.src.match("fresh_sign.png"))) {
  1222. upd_img_pic.src = "images/blank_icon.gif";
  1223. }
  1224. active_post_id = id;
  1225. var query = "?op=rpc&subop=catchupSelected" +
  1226. "&cmode=0&ids=" + param_escape(id);
  1227. new Ajax.Request("backend.php", {
  1228. parameters: query,
  1229. onComplete: function(transport) {
  1230. handle_rpc_json(transport);
  1231. } });
  1232. return true;
  1233. }
  1234. } else {
  1235. toggleSelected(id, true);
  1236. toggleUnread(id, 0, false);
  1237. zoomToArticle(event, id);
  1238. }
  1239. } catch (e) {
  1240. exception_error("cdmClicked");
  1241. }
  1242. return false;
  1243. }
  1244. function postClicked(event, id) {
  1245. try {
  1246. if (!event.ctrlKey) {
  1247. return true;
  1248. } else {
  1249. postOpenInNewTab(event, id);
  1250. return false;
  1251. }
  1252. } catch (e) {
  1253. exception_error("postClicked");
  1254. }
  1255. }
  1256. function hlOpenInNewTab(event, id) {
  1257. toggleUnread(id, 0, false);
  1258. zoomToArticle(event, id);
  1259. }
  1260. function postOpenInNewTab(event, id) {
  1261. closeArticlePanel(id);
  1262. zoomToArticle(event, id);
  1263. }
  1264. function hlClicked(event, id) {
  1265. try {
  1266. if (event.which == 2) {
  1267. view(id);
  1268. return true;
  1269. } else if (event.altKey) {
  1270. openArticleInNewWindow(id);
  1271. } else if (!event.ctrlKey) {
  1272. view(id);
  1273. return false;
  1274. } else {
  1275. toggleSelected(id);
  1276. toggleUnread(id, 0, false);
  1277. zoomToArticle(event, id);
  1278. return false;
  1279. }
  1280. } catch (e) {
  1281. exception_error("hlClicked");
  1282. }
  1283. }
  1284. function getFirstVisibleHeadlineId() {
  1285. var rows = getVisibleArticleIds();
  1286. return rows[0];
  1287. }
  1288. function getLastVisibleHeadlineId() {
  1289. var rows = getVisibleArticleIds();
  1290. return rows[rows.length-1];
  1291. }
  1292. function openArticleInNewWindow(id) {
  1293. toggleUnread(id, 0, false);
  1294. window.open("backend.php?op=la&id=" + id);
  1295. }
  1296. function isCdmMode() {
  1297. return getInitParam("combined_display_mode");
  1298. }
  1299. function markHeadline(id) {
  1300. var row = $("RROW-" + id);
  1301. if (row) {
  1302. var check = $("RCHK-" + id);
  1303. if (check) {
  1304. check.checked = true;
  1305. }
  1306. row.addClassName("Selected");
  1307. }
  1308. }
  1309. function getRelativePostIds(id, limit) {
  1310. var tmp = [];
  1311. try {
  1312. if (!limit) limit = 6; //3
  1313. var ids = getVisibleArticleIds();
  1314. for (var i = 0; i < ids.length; i++) {
  1315. if (ids[i] == id) {
  1316. for (var k = 1; k <= limit; k++) {
  1317. //if (i > k-1) tmp.push(ids[i-k]);
  1318. if (i < ids.length-k) tmp.push(ids[i+k]);
  1319. }
  1320. break;
  1321. }
  1322. }
  1323. } catch (e) {
  1324. exception_error("getRelativePostIds", e);
  1325. }
  1326. return tmp;
  1327. }
  1328. function correctHeadlinesOffset(id) {
  1329. try {
  1330. var container = $("headlines-frame");
  1331. var row = $("RROW-" + id);
  1332. var viewport = container.offsetHeight;
  1333. var rel_offset_top = row.offsetTop - container.scrollTop;
  1334. var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
  1335. //console.log("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
  1336. //console.log("Vport: " + viewport);
  1337. if (rel_offset_top <= 0 || rel_offset_top > viewport) {
  1338. container.scrollTop = row.offsetTop;
  1339. } else if (rel_offset_bottom > viewport) {
  1340. /* doesn't properly work with Opera in some cases because
  1341. Opera fucks up element scrolling */
  1342. container.scrollTop = row.offsetTop + row.offsetHeight - viewport;
  1343. }
  1344. } catch (e) {
  1345. exception_error("correctHeadlinesOffset", e);
  1346. }
  1347. }
  1348. function headlineActionsChange(elem) {
  1349. try {
  1350. eval(elem.value);
  1351. elem.attr('value', 'false');
  1352. } catch (e) {
  1353. exception_error("headlineActionsChange", e);
  1354. }
  1355. }
  1356. function closeArticlePanel() {
  1357. var tabs = dijit.byId("content-tabs");
  1358. var child = tabs.selectedChildWidget;
  1359. if (child && tabs.getIndexOfChild(child) > 0) {
  1360. tabs.removeChild(child);
  1361. child.destroy();
  1362. } else {
  1363. if (dijit.byId("content-insert"))
  1364. dijit.byId("headlines-wrap-inner").removeChild(
  1365. dijit.byId("content-insert"));
  1366. }
  1367. }
  1368. function initHeadlinesMenu() {
  1369. try {
  1370. if (dijit.byId("headlinesMenu"))
  1371. dijit.byId("headlinesMenu").destroyRecursive();
  1372. var ids = [];
  1373. if (!isCdmMode()) {
  1374. nodes = $$("#headlines-frame > div[id*=RROW]");
  1375. } else {
  1376. nodes = $$("#headlines-frame span[id*=RTITLE]");
  1377. }
  1378. nodes.each(function(node) {
  1379. ids.push(node.id);
  1380. });
  1381. var menu = new dijit.Menu({
  1382. id: "headlinesMenu",
  1383. targetNodeIds: ids,
  1384. });
  1385. var tmph = dojo.connect(menu, '_openMyself', function (event) {
  1386. var callerNode = event.target, match = null, tries = 0;
  1387. while (match == null && callerNode && tries <= 3) {
  1388. match = callerNode.id.match("^[A-Z]+[-]([0-9]+)$");
  1389. callerNode = callerNode.parentNode;
  1390. ++tries;
  1391. }
  1392. if (match) this.callerRowId = parseInt(match[1]);
  1393. });
  1394. /* if (!isCdmMode())
  1395. menu.addChild(new dijit.MenuItem({
  1396. label: __("View article"),
  1397. onClick: function(event) {
  1398. view(this.getParent().callerRowId);
  1399. }})); */
  1400. menu.addChild(new dijit.MenuItem({
  1401. label: __("Open original article"),
  1402. onClick: function(event) {
  1403. openArticleInNewWindow(this.getParent().callerRowId);
  1404. }}));
  1405. menu.addChild(new dijit.MenuItem({
  1406. label: __("View in a tt-rss tab"),
  1407. onClick: function(event) {
  1408. hlOpenInNewTab(event, this.getParent().callerRowId);
  1409. }}));
  1410. // menu.addChild(new dijit.MenuSeparator());
  1411. var labels = dijit.byId("feedTree").model.getItemsInCategory(-2);
  1412. if (labels) {
  1413. menu.addChild(new dijit.MenuSeparator());
  1414. var labelAddMenu = new dijit.Menu({ownerMenu: menu});
  1415. var labelDelMenu = new dijit.Menu({ownerMenu: menu});
  1416. labels.each(function(label) {
  1417. var id = label.id[0];
  1418. var bare_id = id.substr(id.indexOf(":")+1);
  1419. var name = label.name[0];
  1420. bare_id = -11-bare_id;
  1421. labelAddMenu.addChild(new dijit.MenuItem({
  1422. label: name,
  1423. labelId: bare_id,
  1424. onClick: function(event) {
  1425. selectionAssignLabel(this.labelId,
  1426. [this.getParent().ownerMenu.callerRowId]);
  1427. }}));
  1428. labelDelMenu.addChild(new dijit.MenuItem({
  1429. label: name,
  1430. labelId: bare_id,
  1431. onClick: function(event) {
  1432. selectionRemoveLabel(this.labelId,
  1433. [this.getParent().ownerMenu.callerRowId]);
  1434. }}));
  1435. });
  1436. menu.addChild(new dijit.PopupMenuItem({
  1437. label: __("Assign label"),
  1438. popup: labelAddMenu,
  1439. }));
  1440. menu.addChild(new dijit.PopupMenuItem({
  1441. label: __("Remove label"),
  1442. popup: labelDelMenu,
  1443. }));
  1444. }
  1445. menu.startup();
  1446. } catch (e) {
  1447. exception_error("initHeadlinesMenu", e);
  1448. }
  1449. }
  1450. function tweetArticle(id) {
  1451. try {
  1452. var query = "?op=rpc&subop=getTweetInfo&id=" + param_escape(id);
  1453. console.log(query);
  1454. var d = new Date();
  1455. var ts = d.getTime();
  1456. var w = window.open('backend.php?op=loading', 'ttrss_tweet',
  1457. "status=0,toolbar=0,location=0,width=500,height=400,scrollbars=1,menubar=0");
  1458. new Ajax.Request("backend.php", {
  1459. parameters: query,
  1460. onComplete: function(transport) {
  1461. var ti = JSON.parse(transport.responseText);
  1462. var share_url = "http://twitter.com/share?_=" + ts +
  1463. "&text=" + param_escape(ti.title) +
  1464. "&url=" + param_escape(ti.link);
  1465. w.location.href = share_url;
  1466. } });
  1467. } catch (e) {
  1468. exception_error("tweetArticle", e);
  1469. }
  1470. }
  1471. function editArticleNote(id) {
  1472. try {
  1473. var query = "backend.php?op=dlg&id=editArticleNote&param=" + param_escape(id);
  1474. if (dijit.byId("editNoteDlg"))
  1475. dijit.byId("editNoteDlg").destroyRecursive();
  1476. dialog = new dijit.Dialog({
  1477. id: "editNoteDlg",
  1478. title: __("Edit article note"),
  1479. style: "width: 600px",
  1480. execute: function() {
  1481. if (this.validate()) {
  1482. var query = dojo.objectToQuery(this.attr('value'));
  1483. notify_progress("Saving article note...", true);
  1484. new Ajax.Request("backend.php", {
  1485. parameters: query,
  1486. onComplete: function(transport) {
  1487. notify('');
  1488. dialog.hide();
  1489. var reply = JSON.parse(transport.responseText);
  1490. cache_delete("article:" + id);
  1491. var elem = $("POSTNOTE-" + id);
  1492. if (elem) {
  1493. Element.hide(elem);
  1494. elem.innerHTML = reply.note;
  1495. if (reply.raw_length != 0)
  1496. new Effect.Appear(elem);
  1497. }
  1498. }});
  1499. }
  1500. },
  1501. href: query,
  1502. });
  1503. dialog.show();
  1504. } catch (e) {
  1505. exception_error("editArticleNote", e);
  1506. }
  1507. }
  1508. function player(elem) {
  1509. var aid = elem.getAttribute("audio-id");
  1510. var status = elem.getAttribute("status");
  1511. var audio = $(aid);
  1512. if (audio) {
  1513. if (status == 0) {
  1514. audio.play();
  1515. status = 1;
  1516. elem.innerHTML = __("Playing...");
  1517. elem.title = __("Click to pause");
  1518. elem.addClassName("playing");
  1519. } else {
  1520. audio.pause();
  1521. status = 0;
  1522. elem.innerHTML = __("Play");
  1523. elem.title = __("Click to play");
  1524. elem.removeClassName("playing");
  1525. }
  1526. elem.setAttribute("status", status);
  1527. } else {
  1528. alert("Your browser doesn't seem to support HTML5 audio.");
  1529. }
  1530. }
  1531. function cache_set(id, obj) {
  1532. //console.log("cache_set: " + id);
  1533. if (has_storage)
  1534. try {
  1535. sessionStorage[id] = obj;
  1536. } catch (e) {
  1537. sessionStorage.clear();
  1538. }
  1539. }
  1540. function cache_get(id) {
  1541. if (has_storage)
  1542. return sessionStorage[id];
  1543. }
  1544. function cache_clear() {
  1545. if (has_storage)
  1546. sessionStorage.clear();
  1547. }
  1548. function cache_delete(id) {
  1549. if (has_storage)
  1550. sessionStorage.removeItem(id);
  1551. }
  1552. function cache_headlines(feed, is_cat, toolbar_obj, content_obj) {
  1553. if (toolbar_obj && content_obj) {
  1554. cache_set("feed:" + feed + ":" + is_cat,
  1555. JSON.stringify({toolbar: toolbar_obj, content: content_obj}));
  1556. } else {
  1557. try {
  1558. obj = cache_get("feed:" + feed + ":" + is_cat);
  1559. if (obj) {
  1560. obj = JSON.parse(obj);
  1561. if (toolbar_obj) obj.toolbar = toolbar_obj;
  1562. if (content_obj) obj.content = content_obj;
  1563. cache_set("feed:" + feed + ":" + is_cat, JSON.stringify(obj));
  1564. }
  1565. } catch (e) {
  1566. console.warn("cache_headlines failed: " + e);
  1567. }
  1568. }
  1569. }
  1570. function render_local_headlines(feed, is_cat, obj) {
  1571. try {
  1572. dijit.byId("headlines-toolbar").attr('content',
  1573. obj.toolbar);
  1574. dijit.byId("headlines-frame").attr('content',
  1575. obj.content);
  1576. dojo.parser.parse('headlines-toolbar');
  1577. $("headlines-frame").scrollTop = 0;
  1578. selectArticles('none');
  1579. setActiveFeedId(feed, is_cat);
  1580. initHeadlinesMenu();
  1581. precache_headlines();
  1582. } catch (e) {
  1583. exception_error("render_local_headlines", e);
  1584. }
  1585. }
  1586. function precache_headlines_idle() {
  1587. try {
  1588. if (!feed_precache_timeout_id) {
  1589. var feeds = dijit.byId("feedTree").getVisibleUnreadFeeds();
  1590. var uncached = [];
  1591. feeds.each(function(item) {
  1592. if (parseInt(item[0]) > 0 && !cache_get("feed:" + item[0] + ":" + item[1]))
  1593. uncached.push(item);
  1594. });
  1595. if (uncached.length > 0) {
  1596. var rf = uncached[Math.floor(Math.random()*uncached.length)];
  1597. viewfeed(rf[0], '', rf[1], 0, true);
  1598. }
  1599. }
  1600. precache_idle_timeout_id = setTimeout("precache_headlines_idle()", 1000*30);
  1601. } catch (e) {
  1602. exception_error("precache_headlines_idle", e);
  1603. }
  1604. }
  1605. function precache_headlines() {
  1606. try {
  1607. if (!feed_precache_timeout_id) {
  1608. feed_precache_timeout_id = window.setTimeout(function() {
  1609. var nuf = getNextUnreadFeed(getActiveFeedId(), activeFeedIsCat());
  1610. var nf = dijit.byId("feedTree").getNextFeed(getActiveFeedId(), activeFeedIsCat());
  1611. if (nuf && !cache_get("feed:" + nuf + ":" + activeFeedIsCat()))
  1612. viewfeed(nuf, '', activeFeedIsCat(), 0, true);
  1613. if (nf != nuf && nf && !cache_get("feed:" + nf[0] + ":" + nf[1]))
  1614. viewfeed(nf[0], '', nf[1], 0, true);
  1615. window.setTimeout(function() {
  1616. feed_precache_timeout_id = false;
  1617. }, 3000);
  1618. }, 1000);
  1619. }
  1620. } catch (e) {
  1621. exception_error("precache_headlines", e);
  1622. }
  1623. }
  1624. function shareArticle(id) {
  1625. try {
  1626. if (dijit.byId("shareArticleDlg"))
  1627. dijit.byId("shareArticleDlg").destroyRecursive();
  1628. var query = "backend.php?op=dlg&id=shareArticle&param=" + param_escape(id);
  1629. dialog = new dijit.Dialog({
  1630. id: "shareArticleDlg",
  1631. title: __("Share article by URL"),
  1632. style: "width: 600px",
  1633. href: query});
  1634. dialog.show();
  1635. } catch (e) {
  1636. exception_error("emailArticle", e);
  1637. }
  1638. }