diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/FeedTree.js | 2 | ||||
-rw-r--r-- | js/PluginHost.js | 34 | ||||
-rw-r--r-- | js/feedlist.js | 3 | ||||
-rw-r--r-- | js/functions.js | 143 | ||||
-rw-r--r-- | js/index.html | 0 | ||||
-rw-r--r-- | js/prefs.js | 49 | ||||
-rw-r--r-- | js/tt-rss.js | 27 | ||||
-rw-r--r-- | js/viewfeed.js | 138 |
8 files changed, 211 insertions, 185 deletions
diff --git a/js/FeedTree.js b/js/FeedTree.js index f874db702..07c3002f2 100644 --- a/js/FeedTree.js +++ b/js/FeedTree.js @@ -100,7 +100,7 @@ dojo.declare("fox.FeedTree", dijit.Tree, { _createTreeNode: function(args) { var tnode = new dijit._TreeNode(args); - if (args.item.icon) + if (args.item.icon && args.item.icon[0]) tnode.iconNode.src = args.item.icon[0]; var id = args.item.id[0]; diff --git a/js/PluginHost.js b/js/PluginHost.js new file mode 100644 index 000000000..668d215f9 --- /dev/null +++ b/js/PluginHost.js @@ -0,0 +1,34 @@ +// based on http://www.velvetcache.org/2010/08/19/a-simple-javascript-hooks-system + +var PluginHost = { + HOOK_ARTICLE_RENDERED: 1, + HOOK_ARTICLE_RENDERED_CDM: 2, + HOOK_ARTICLE_SET_ACTIVE: 3, + HOOK_FEED_SET_ACTIVE: 4, + HOOK_FEED_LOADED: 5, + HOOK_ARTICLE_EXPANDED: 6, + HOOK_ARTICLE_COLLAPSED: 7, + HOOK_PARAMS_LOADED: 8, + HOOK_RUNTIME_INFO_LOADED: 9, + hooks: [], + register: function (name, callback) { + if (typeof(this.hooks[name]) == 'undefined') + this.hooks[name] = []; + + this.hooks[name].push(callback); + }, + run: function (name, args) { + console.warn('PluginHost::run ' + name); + + if (typeof(this.hooks[name]) != 'undefined') + for (i = 0; i < this.hooks[name].length; i++) + if (!this.hooks[name][i](args)) break; + } +}; + +/* PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED, + function (args) { console.log('ARTICLE_RENDERED: ' + args); return true; }); + +PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED_CDM, + function (args) { console.log('ARTICLE_RENDERED_CDM: ' + args); return true; }); */ + diff --git a/js/feedlist.js b/js/feedlist.js index f4e07517e..932297be8 100644 --- a/js/feedlist.js +++ b/js/feedlist.js @@ -139,6 +139,7 @@ function viewfeed(feed, method, is_cat, offset, background, infscroll_req) { onComplete: function(transport) { setFeedExpandoIcon(feed, is_cat, 'images/blank_icon.gif'); headlines_callback2(transport, offset, background, infscroll_req); + PluginHost.run(PluginHost.HOOK_FEED_LOADED, [feed, is_cat]); } }); } catch (e) { @@ -150,6 +151,8 @@ function feedlist_init() { try { console.log("in feedlist init"); + loading_set_progress(50); + document.onkeydown = hotkey_handler; setTimeout("hotkey_prefix_timeout()", 5*1000); diff --git a/js/functions.js b/js/functions.js index 82cfa9054..8691c1ee5 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1,8 +1,8 @@ -var notify_silent = false; var loading_progress = 0; var sanity_check_done = false; var init_params = {}; var _label_base_index = -1024; +var notify_hide_timerid = false; Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap( function (callOriginal, options) { @@ -50,6 +50,21 @@ function exception_error(location, e, ext_info) { } } + try { + new Ajax.Request("backend.php", { + parameters: {op: "rpc", method: "log", logmsg: msg}, + onComplete: function (transport) { + console.log(transport.responseText); + } }); + + } catch (eii) { + console.log("Exception while trying to log the error."); + console.log(eii); + } + + msg += "<p>"+ __("The error will be reported to the configured log destination.") + + "</p>"; + var content = "<div class=\"fatalError\">" + "<pre>" + msg + "</pre>"; @@ -106,7 +121,28 @@ function exception_error(location, e, ext_info) { dialog.show(); - } catch (e) { + } catch (ei) { + console.log("Exception while trying to report an exception. Oh boy."); + console.log(ei); + console.log("Original exception:"); + console.log(e); + + msg += "\n\nAdditional exception caught while trying to show the error dialog.\n\n" + format_exception_error('exception_error', ei); + + try { + new Ajax.Request("backend.php", { + parameters: {op: "rpc", method: "log", logmsg: msg}, + onComplete: function (transport) { + console.log(transport.responseText); + } }); + + } catch (eii) { + console.log("Third exception while trying to log the error! Seriously?"); + console.log(eii); + } + + msg += "\n\nThe error will be reported to the configured log destination."; + alert(msg); } @@ -147,42 +183,28 @@ function param_unescape(arg) { return unescape(arg); } -var notify_hide_timerid = false; function hide_notify() { - var n = $("notify"); - if (n) { - n.style.display = "none"; - } -} - -function notify_silent_next() { - notify_silent = true; + Element.hide('notify'); } function notify_real(msg, no_hide, n_type) { - if (notify_silent) { - notify_silent = false; - return; - } - var n = $("notify"); - var nb = $("notify_body"); - if (!n || !nb) return; + if (!n) return; if (notify_hide_timerid) { window.clearTimeout(notify_hide_timerid); } if (msg == "") { - if (n.style.display == "block") { + if (Element.visible(n)) { notify_hide_timerid = window.setTimeout("hide_notify()", 0); } return; } else { - n.style.display = "block"; + Element.show(n); } /* types: @@ -194,33 +216,31 @@ function notify_real(msg, no_hide, n_type) { */ - msg = __(msg); + msg = "<span class=\"msg\"> " + __(msg) + "</span>"; if (n_type == 1) { n.className = "notify"; } else if (n_type == 2) { n.className = "notify progress"; - msg = "<img src='images/indicator_white.gif'> " + msg; + msg = "<span><img src='images/indicator_white.gif'></span>" + msg; + no_hide = true; } else if (n_type == 3) { n.className = "notify error"; - msg = "<img src='images/sign_excl.svg'> " + msg; + msg = "<span><img src='images/sign_excl.svg'></span>" + msg; } else if (n_type == 4) { n.className = "notify info"; - msg = "<img src='images/sign_info.svg'> " + msg; - } - - if (no_hide) { - msg += " <span>(<a href='#' onclick=\"notify('')\">" + - __("close") + "</a>)</span>"; + msg = "<span><img src='images/sign_info.svg'></span>" + msg; } + msg += " <span><img src=\"images/close_notify.svg\" class=\"close\" title=\"" + + __("Click to close") + "\" onclick=\"notify('')\"></span>"; // msg = "<img src='images/live_com_loading.gif'> " + msg; - nb.innerHTML = msg; + n.innerHTML = msg; if (!no_hide) { - notify_hide_timerid = window.setTimeout("hide_notify()", 3000); + notify_hide_timerid = window.setTimeout("hide_notify()", 5*1000); } } @@ -368,6 +388,9 @@ function toggleSelectRow2(sender, row, is_cdm) { row.addClassName('Selected'); else row.removeClassName('Selected'); + + if (typeof updateSelectedPrompt != undefined) + updateSelectedPrompt(); } @@ -379,6 +402,9 @@ function toggleSelectRow(sender, row) { row.addClassName('Selected'); else row.removeClassName('Selected'); + + if (typeof updateSelectedPrompt != undefined) + updateSelectedPrompt(); } function checkboxToggleElement(elem, id) { @@ -810,7 +836,7 @@ function quickAddFeed() { notify(''); Element.hide("feed_add_spinner"); - console.log("GOT RC: " + rc); + console.log(rc); switch (parseInt(rc['code'])) { case 1: @@ -826,39 +852,6 @@ function quickAddFeed() { alert(__("Specified URL doesn't seem to contain any feeds.")); break; case 4: - /* notify_progress("Searching for feed urls...", true); - - new Ajax.Request("backend.php", { - parameters: 'op=rpc&method=extractfeedurls&url=' + param_escape(feed_url), - onComplete: function(transport, dialog, feed_url) { - - notify(''); - - var reply = JSON.parse(transport.responseText); - - var feeds = reply['urls']; - - console.log(transport.responseText); - - var select = dijit.byId("feedDlg_feedContainerSelect"); - - while (select.getOptions().length > 0) - select.removeOption(0); - - var count = 0; - for (var feedUrl in feeds) { - select.addOption({value: feedUrl, label: feeds[feedUrl]}); - count++; - } - -// if (count > 5) count = 5; -// select.size = count; - - Effect.Appear('feedDlg_feedsContainer', {duration : 0.5}); - } - }); - break; */ - feeds = rc['feeds']; var select = dijit.byId("feedDlg_feedContainerSelect"); @@ -866,6 +859,8 @@ function quickAddFeed() { while (select.getOptions().length > 0) select.removeOption(0); + select.addOption({value: '', label: __("Expand to select feed")}); + var count = 0; for (var feedUrl in feeds) { select.addOption({value: feedUrl, label: feeds[feedUrl]}); @@ -879,6 +874,11 @@ function quickAddFeed() { alert(__("Couldn't download the specified URL: %s"). replace("%s", rc['message'])); break; + case 6: + alert(__("XML validation failed: %s"). + replace("%s", rc['message'])); + break; + break; case 0: alert(__("You are already subscribed to this feed.")); break; @@ -1269,16 +1269,17 @@ function backend_sanity_check_callback(transport) { if (params) { console.log('reading init-params...'); - if (params) { - for (k in params) { - var v = params[k]; - console.log("IP: " + k + " => " + v); + for (k in params) { + var v = params[k]; + console.log("IP: " + k + " => " + v); - if (k == "label_base_index") _label_base_index = parseInt(v); - } + if (k == "label_base_index") _label_base_index = parseInt(v); } init_params = params; + + // PluginHost might not be available on non-index pages + window.PluginHost && PluginHost.run(PluginHost.HOOK_PARAMS_LOADED, init_params); } sanity_check_done = true; diff --git a/js/index.html b/js/index.html new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/js/index.html diff --git a/js/prefs.js b/js/prefs.js index b1decede5..e226459fc 100644 --- a/js/prefs.js +++ b/js/prefs.js @@ -852,6 +852,15 @@ function updatePrefsList() { } }); } +function updateSystemList() { + new Ajax.Request("backend.php", { + parameters: "?op=pref-system", + onComplete: function(transport) { + dijit.byId('systemConfigTab').attr('content', transport.responseText); + notify(""); + } }); +} + function selectTab(id, noupdate, method) { try { if (!noupdate) { @@ -867,6 +876,8 @@ function selectTab(id, noupdate, method) { updatePrefsList(); } else if (id == "userConfig") { updateUsersList(); + } else if (id == "systemConfig") { + updateSystemList(); } var tab = dijit.byId(id + "Tab"); @@ -951,8 +962,11 @@ function init() { dojo.addOnLoad(function() { loading_set_progress(50); + var clientTzOffset = new Date().getTimezoneOffset() * 60; + new Ajax.Request("backend.php", { - parameters: {op: "rpc", method: "sanityCheck"}, + parameters: {op: "rpc", method: "sanityCheck", + clientTzOffset: clientTzOffset }, onComplete: function(transport) { backend_sanity_check_callback(transport); } }); @@ -1596,21 +1610,6 @@ function resetCatOrder() { } } -function toggleHiddenFeedCats() { - try { - notify_progress("Loading, please wait..."); - - new Ajax.Request("backend.php", { - parameters: "?op=pref-feeds&method=togglehiddenfeedcats", - onComplete: function(transport) { - updateFeedList(); - } }); - - } catch (e) { - exception_error("toggleHiddenFeedCats"); - } -} - function editCat(id, item, event) { try { var new_name = prompt(__('Rename category to:'), item.name); @@ -1819,3 +1818,21 @@ function clearPluginData(name) { exception_error("clearPluginData", e); } } + +function clearSqlLog() { + + if (confirm(__("Clear all messages in the error log?"))) { + + notify_progress("Loading, please wait..."); + var query = "?op=pref-system&method=clearLog"; + + new Ajax.Request("backend.php", { + parameters: query, + onComplete: function(transport) { + updateSystemList(); + } }); + + } +} + + diff --git a/js/tt-rss.js b/js/tt-rss.js index a572e5324..577922948 100644 --- a/js/tt-rss.js +++ b/js/tt-rss.js @@ -40,6 +40,8 @@ function setActiveFeedId(id, is_cat) { $("headlines-frame").setAttribute("is-cat", is_cat ? 1 : 0); selectFeed(id, is_cat); + + PluginHost.run(PluginHost.HOOK_FEED_SET_ACTIVE, _active_article_id); } catch (e) { exception_error("setActiveFeedId", e); } @@ -134,7 +136,8 @@ function catchupAllFeeds() { new Ajax.Request("backend.php", { parameters: query_str, onComplete: function(transport) { - feedlist_callback2(transport); + request_counters(true); + viewCurrentFeed(); } }); global_unread = 0; @@ -246,13 +249,19 @@ function init() { if (!genericSanityCheck()) return false; - loading_set_progress(20); + loading_set_progress(30); + + var a = document.createElement('audio'); - var hasAudio = !!((myAudioTag = document.createElement('audio')).canPlayType); + var hasAudio = !!a.canPlayType; var hasSandbox = "sandbox" in document.createElement("iframe"); + var hasMp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '')); + var clientTzOffset = new Date().getTimezoneOffset() * 60; new Ajax.Request("backend.php", { parameters: {op: "rpc", method: "sanityCheck", hasAudio: hasAudio, + hasMp3: hasMp3, + clientTzOffset: clientTzOffset, hasSandbox: hasSandbox}, onComplete: function(transport) { backend_sanity_check_callback(transport); @@ -302,7 +311,7 @@ function init() { var id = getActiveArticleId(); var elem = $("CICD-"+id); if(elem.visible()) { - cdmUnexpandArticle(null, id); + cdmCollapseArticle(null, id, false); } else { cdmExpandArticle(id); @@ -323,7 +332,7 @@ function init() { hotkey_actions["edit_tags"] = function() { var id = getActiveArticleId(); if (id) { - editArticleTags(id, getActiveFeedId(), isCdmMode()); + editArticleTags(id); }; } hotkey_actions["dismiss_selected"] = function() { @@ -564,7 +573,7 @@ function init_second_stage() { setActiveFeedId(hash_feed_id, hash_feed_is_cat); } - loading_set_progress(30); + loading_set_progress(50); // can't use cache_clear() here because viewfeed might not have initialized yet if ('sessionStorage' in window && window['sessionStorage'] !== null) @@ -744,6 +753,8 @@ function parse_runtime_info(data) { init_params[k] = v; notify(''); } + + PluginHost.run(PluginHost.HOOK_RUNTIME_INFO_LOADED, data); } function collapse_feedlist() { @@ -983,7 +994,7 @@ function handle_rpc_json(transport, scheduled_call) { if (counters) parse_counters(counters, scheduled_call); - var runtime_info = reply['runtime-info'];; + var runtime_info = reply['runtime-info']; if (runtime_info) parse_runtime_info(runtime_info); @@ -1072,7 +1083,7 @@ function hash_get(key) { kv = window.location.hash.substring(1).toQueryParams(); return kv[key]; } catch (e) { - exception_error("hash_set", e); + exception_error("hash_get", e); } } function hash_set(key, value) { diff --git a/js/viewfeed.js b/js/viewfeed.js index da5ded64f..da3628349 100644 --- a/js/viewfeed.js +++ b/js/viewfeed.js @@ -20,8 +20,6 @@ function headlines_callback2(transport, offset, background, infscroll_req) { try { handle_rpc_json(transport); - loading_set_progress(25); - console.log("headlines_callback2 [offset=" + offset + "] B:" + background + " I:" + infscroll_req); var is_cat = false; @@ -43,9 +41,7 @@ function headlines_callback2(transport, offset, background, infscroll_req) { if (background) { var content = reply['headlines']['content']; - if (getInitParam("cdm_auto_catchup") == 1) { - content = content + "<div id='headlines-spacer'></div>"; - } + content = content + "<div id='headlines-spacer'></div>"; return; } @@ -93,11 +89,9 @@ function headlines_callback2(transport, offset, background, infscroll_req) { } }); - if (getInitParam("cdm_auto_catchup") == 1) { - var hsp = $("headlines-spacer"); - if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"}); - dijit.byId('headlines-frame').domNode.appendChild(hsp); - } + var hsp = $("headlines-spacer"); + if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"}); + dijit.byId('headlines-frame').domNode.appendChild(hsp); initHeadlinesMenu(); @@ -140,8 +134,6 @@ function headlines_callback2(transport, offset, background, infscroll_req) { if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"}); - fixHeadlinesOrder(getLoadedArticleIds()); - if (getInitParam("cdm_auto_catchup") == 1) { c.domNode.appendChild(hsp); } @@ -232,6 +224,8 @@ function render_article(article) { c.domNode.scrollTop = 0; } catch (e) { }; + PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED, article); + c.attr('content', article); correctHeadlinesOffset(getActiveArticleId()); @@ -639,11 +633,33 @@ function toggleSelected(id, force_on) { if (cb) cb.attr("checked", true); } } + + updateSelectedPrompt(); } catch (e) { exception_error("toggleSelected", e); } } +function updateSelectedPrompt() { + try { + var count = getSelectedArticleIds2().size(); + var elem = $("selected_prompt"); + + if (elem) { + elem.innerHTML = ngettext("%d article selected", + "%d articles selected", count).replace("%d", count); + + if (count > 0) + Element.show(elem); + else + Element.hide(elem); + } + + } catch (e) { + exception_error("updateSelectedPrompt", e); + } +} + function toggleUnread_afh(effect) { try { @@ -960,6 +976,8 @@ function selectArticles(mode) { } }); + updateSelectedPrompt(); + } catch (e) { exception_error("selectArticles", e); } @@ -1169,6 +1187,7 @@ function cdmScrollToArticleId(id, force) { function setActiveArticleId(id) { _active_article_id = id; + PluginHost.run(PluginHost.HOOK_ARTICLE_SET_ACTIVE, _active_article_id); } function getActiveArticleId() { @@ -1195,6 +1214,8 @@ function unpackVisibleHeadlines() { var cencw = $("CENCW-" + child.id.replace("RROW-", "")); if (cencw) { + PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED_CDM, child); + cencw.innerHTML = htmlspecialchars_decode(cencw.innerHTML); cencw.setAttribute('id', ''); Element.show(cencw); @@ -1370,8 +1391,10 @@ function catchupRelativeToArticle(below, id) { } } -function cdmCollapseArticle(event, id) { +function cdmCollapseArticle(event, id, unmark) { try { + if (unmark == undefined) unmark = true; + var row = $("RROW-" + id); var elem = $("CICD-" + id); @@ -1382,40 +1405,26 @@ function cdmCollapseArticle(event, id) { Element.hide(elem); Element.show("CEXC-" + id); Element.hide(collapse); - row.removeClassName("active"); - - markHeadline(id, false); - - if (id == getActiveArticleId()) { - setActiveArticleId(0); - } - - if (event) Event.stop(event); - } - } catch (e) { - exception_error("cdmCollapseArticle", e); - } -} + if (unmark) { + row.removeClassName("active"); -function cdmUnexpandArticle(event, id) { - try { - var row = $("RROW-" + id); - var elem = $("CICD-" + id); + markHeadline(id, false); - if (elem && row) { - var collapse = $$("div#RROW-" + id + - " span[class='collapseBtn']")[0]; + if (id == getActiveArticleId()) { + setActiveArticleId(0); + } - Element.hide(elem); - Element.show("CEXC-" + id); - Element.hide(collapse); + updateSelectedPrompt(); + } if (event) Event.stop(event); + + PluginHost.run(PluginHost.HOOK_ARTICLE_COLLAPSED, id); } } catch (e) { - exception_error("cdmUnexpandArticle", e); + exception_error("cdmCollapseArticle", e); } } @@ -1478,6 +1487,8 @@ function cdmExpandArticle(id, noexpand) { toggleSelected(id); $("RROW-" + id).addClassName("active"); + PluginHost.run(PluginHost.HOOK_ARTICLE_EXPANDED, id); + } catch (e) { exception_error("cdmExpandArticle", e); } @@ -1485,26 +1496,6 @@ function cdmExpandArticle(id, noexpand) { return false; } -function fixHeadlinesOrder(ids) { - try { - for (var i = 0; i < ids.length; i++) { - var e = $("RROW-" + ids[i]); - - if (e) { - if (i % 2 == 0) { - e.removeClassName("even"); - e.addClassName("odd"); - } else { - e.removeClassName("odd"); - e.addClassName("even"); - } - } - } - } catch (e) { - exception_error("fixHeadlinesOrder", e); - } -} - function getArticleUnderPointer() { return post_under_pointer; } @@ -1585,7 +1576,6 @@ function dismissSelectedArticles() { if (sel.length > 0) selectionToggleUnread(false); - fixHeadlinesOrder(tmp); } catch (e) { exception_error("dismissSelectedArticles", e); @@ -1610,8 +1600,6 @@ function dismissReadArticles() { } } - fixHeadlinesOrder(tmp); - } catch (e) { exception_error("dismissSelectedArticles", e); } @@ -2003,34 +1991,6 @@ function initHeadlinesMenu() { } } - -function player(elem) { - var aid = elem.getAttribute("audio-id"); - var status = elem.getAttribute("status"); - - var audio = $(aid); - - if (audio) { - if (status == 0) { - audio.play(); - status = 1; - elem.innerHTML = __("Playing..."); - elem.title = __("Click to pause"); - elem.addClassName("playing"); - } else { - audio.pause(); - status = 0; - elem.innerHTML = __("Play"); - elem.title = __("Click to play"); - elem.removeClassName("playing"); - } - - elem.setAttribute("status", status); - } else { - alert("Your browser doesn't seem to support HTML5 audio."); - } -} - function cache_set(id, obj) { //console.log("cache_set: " + id); if (has_storage) |