';
@@ -1172,7 +1172,7 @@ class Pref_Feeds extends Handler_Protected {
function index() {
print "
";
- print "
rss_feed ".__('Feeds')."\">";
$sth = $this->pdo->prepare("SELECT COUNT(id) AS num_errors
@@ -1307,7 +1307,7 @@ class Pref_Feeds extends Handler_Protected {
print "
"; # feeds pane
- print "
";
print "
" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . "
";
@@ -1360,7 +1360,7 @@ class Pref_Feeds extends Handler_Protected {
print ""; # pane
- print "
share ".__('Published & shared articles / Generated feeds')."\">";
print "
" . __('Published articles can be subscribed by anyone who knows the following URL:') . "
";
@@ -1672,7 +1672,7 @@ class Pref_Feeds extends Handler_Protected {
print "";
print "";
diff --git a/js/App.js b/js/App.js
index f75413c86..0e1473557 100644
--- a/js/App.js
+++ b/js/App.js
@@ -1,8 +1,8 @@
'use strict';
-/* global __, ngettext, Article, Headlines, Filters */
+/* global __, Article, Ajax, Headlines, Filters */
/* global xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Feeds, Cookie */
-/* global CommonDialogs, CommonFilters, Plugins */
+/* global CommonDialogs, Plugins, Effect */
const App = {
_initParams: [],
@@ -12,8 +12,10 @@ const App = {
hotkey_prefix_timeout: 0,
global_unread: -1,
_widescreen_mode: false,
+ _loading_progress: 0,
hotkey_actions: {},
is_prefs: false,
+ LABEL_BASE_INDEX: -1024,
Scrollable: {
scrollByPages: function (elem, page_offset) {
if (!elem) return;
@@ -46,8 +48,14 @@ const App = {
return elem.offsetTop + elem.offsetHeight <= ctr.scrollTop + ctr.offsetHeight &&
elem.offsetTop >= ctr.scrollTop;
}
- },
- getInitParam: function(k) {
+ },
+ label_to_feed_id: function(label) {
+ return this.LABEL_BASE_INDEX - 1 - Math.abs(label);
+ },
+ feed_to_label_id: function(feed) {
+ return this.LABEL_BASE_INDEX - 1 + Math.abs(feed);
+ },
+ getInitParam: function(k) {
return this._initParams[k];
},
setInitParam: function(k, v) {
@@ -130,12 +138,12 @@ const App = {
return this._rpc_seq;
},
setLoadingProgress: function(p) {
- loading_progress += p;
+ this._loading_progress += p;
if (dijit.byId("loading_bar"))
- dijit.byId("loading_bar").update({progress: loading_progress});
+ dijit.byId("loading_bar").update({progress: this._loading_progress});
- if (loading_progress >= 90) {
+ if (this._loading_progress >= 90) {
$("overlay").hide();
}
@@ -223,8 +231,27 @@ const App = {
$$("#" + root + " *").each(function (i) {
i.parentNode ? i.parentNode.removeChild(i) : true;
});
- },
- helpDialog: function(topic) {
+ },
+ // htmlspecialchars()-alike for headlines data-content attribute
+ escapeHtml: function(text) {
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": '''
+ };
+
+ return text.replace(/[&<>"']/g, function(m) { return map[m]; });
+ },
+ displayIfChecked: function(checkbox, elemId) {
+ if (checkbox.checked) {
+ Effect.Appear(elemId, {duration : 0.5});
+ } else {
+ Effect.Fade(elemId, {duration : 0.5});
+ }
+ },
+ helpDialog: function(topic) {
const query = "backend.php?op=backend&method=help&topic=" + encodeURIComponent(topic);
if (dijit.byId("helpDlg"))
@@ -418,7 +445,7 @@ const App = {
if (params.hasOwnProperty(k)) {
switch (k) {
case "label_base_index":
- LABEL_BASE_INDEX = parseInt(params[k]);
+ this.LABEL_BASE_INDEX = parseInt(params[k]);
break;
case "cdm_auto_catchup":
if (params[k] == 1) {
@@ -429,16 +456,17 @@ const App = {
case "hotkeys":
// filter mnemonic definitions (used for help panel) from hotkeys map
// i.e. *(191)|Ctrl-/ -> *(191)
+ {
+ const tmp = [];
+ for (const sequence in params[k][1]) {
+ if (params[k][1].hasOwnProperty(sequence)) {
+ const filtered = sequence.replace(/\|.*$/, "");
+ tmp[filtered] = params[k][1][sequence];
+ }
+ }
- const tmp = [];
- for (const sequence in params[k][1]) {
- if (params[k][1].hasOwnProperty(sequence)) {
- const filtered = sequence.replace(/\|.*$/, "");
- tmp[filtered] = params[k][1][sequence];
- }
- }
-
- params[k][1] = tmp;
+ params[k][1] = tmp;
+ }
break;
}
@@ -587,7 +615,7 @@ const App = {
['MutationObserver'].each(function(wf) {
if (!(wf in window)) {
errorMsg = `Browser feature check failed:
window.${wf}
not found.`;
- throw $break;
+ throw new Error(errorMsg);
}
});
diff --git a/js/Article.js b/js/Article.js
index 5044b6e0e..e7946776e 100644
--- a/js/Article.js
+++ b/js/Article.js
@@ -1,6 +1,6 @@
'use strict'
-/* global __, ngettext, App, Headlines, xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, escapeHtml */
+/* global __, ngettext, App, Headlines, xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Ajax */
const Article = {
_scroll_reset_timeout: false,
@@ -86,6 +86,22 @@ const Article = {
}
}
},
+ popupOpenUrl: function(url) {
+ const w = window.open("");
+
+ w.opener = null;
+ w.location = url;
+ },
+ /* popupOpenArticle: function(id) {
+ const w = window.open("",
+ "ttrss_article_popup",
+ "height=900,width=900,resizable=yes,status=no,location=no,menubar=no,directories=no,scrollbars=yes,toolbar=no");
+
+ if (w) {
+ w.opener = null;
+ w.location = "backend.php?op=article&method=view&mode=raw&html=1&zoom=1&id=" + id + "&csrf_token=" + App.getInitParam("csrf_token");
+ }
+ }, */
cdmUnsetActive: function (event) {
const row = $("RROW-" + Article.getActive());
@@ -157,14 +173,14 @@ const Article = {
comments_msg = hl.num_comments + " " + ngettext("comment", "comments", hl.num_comments)
}
- comments = `
(${comments_msg})`;
+ comments = `
(${comments_msg})`;
}
return comments;
},
formatOriginallyFrom: function(hl) {
return hl.orig_feed ? `
- ${__('Originally from:')} ${hl.orig_feed[0]}
+ ${__('Originally from:')} ${hl.orig_feed[0]}
` : "";
},
unpack: function(row) {
@@ -213,8 +229,8 @@ const Article = {
diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js
index ea178ffca..d3ad35161 100644
--- a/js/CommonDialogs.js
+++ b/js/CommonDialogs.js
@@ -46,18 +46,20 @@ const CommonDialogs = {
xhr.onload = function () {
switch (parseInt(this.responseText)) {
case 0:
- Notify.info("Upload complete.");
+ {
+ Notify.info("Upload complete.");
- if (App.isPrefs())
- dijit.byId("feedTree").reload();
- else
- Feeds.reload();
+ if (App.isPrefs())
+ dijit.byId("feedTree").reload();
+ else
+ Feeds.reload();
- const icon = $$(".feed-editor-icon")[0];
+ const icon = $$(".feed-editor-icon")[0];
- if (icon)
- icon.src = icon.src.replace(/\?[0-9]+$/, "?" + new Date().getTime());
+ if (icon)
+ icon.src = icon.src.replace(/\?[0-9]+$/, "?" + new Date().getTime());
+ }
break;
case 1:
Notify.error("Upload failed: icon is too big.");
diff --git a/js/CommonFilters.js b/js/CommonFilters.js
index c34380526..9676abe9e 100644
--- a/js/CommonFilters.js
+++ b/js/CommonFilters.js
@@ -1,7 +1,7 @@
'use strict'
-/* global __, ngettext, App, Article, Lists */
-/* global xhrPost, xhrJson, dojo, dijit, Notify, $$, Feeds */
+/* global __, App, Article, Lists, Effect */
+/* global xhrPost, dojo, dijit, Notify, $$, Feeds */
const Filters = {
filterDlgCheckAction: function(sender) {
@@ -337,6 +337,7 @@ const Filters = {
});
if (!App.isPrefs()) {
+ /* global getSelectionText */
const selectedText = getSelectionText();
const lh = dojo.connect(dialog, "onLoad", function () {
diff --git a/js/FeedTree.js b/js/FeedTree.js
index 4e8f5930e..ae39728bb 100755
--- a/js/FeedTree.js
+++ b/js/FeedTree.js
@@ -1,4 +1,4 @@
-/* global dojo, dijit, define, App, Feeds, CommonDialogs, LABEL_BASE_INDEX */
+/* global dojo, dijit, define, App, Feeds, CommonDialogs */
define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"], function (declare, domConstruct) {
@@ -34,7 +34,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
const id = args.item.id[0];
const bare_id = parseInt(id.substr(id.indexOf(':')+1));
- if (bare_id < LABEL_BASE_INDEX) {
+ if (bare_id < App.LABEL_BASE_INDEX) {
const label = dojo.create('i', { className: "material-icons icon icon-label", innerHTML: "label" });
//const fg_color = args.item.fg_color[0];
@@ -164,9 +164,9 @@ define(["dojo/_base/declare", "dojo/dom-construct", "dijit/Tree", "dijit/Menu"],
if (item.auxcounter > 0) rc += " Has_Aux";
if (item.markedcounter > 0) rc += " Has_Marked";
if (item.updates_disabled > 0) rc += " UpdatesDisabled";
- if (item.bare_id >= LABEL_BASE_INDEX && item.bare_id < 0 && !is_cat || item.bare_id == 0 && !is_cat) rc += " Special";
+ if (item.bare_id >= App.LABEL_BASE_INDEX && item.bare_id < 0 && !is_cat || item.bare_id == 0 && !is_cat) rc += " Special";
if (item.bare_id == -1 && is_cat) rc += " AlwaysVisible";
- if (item.bare_id < LABEL_BASE_INDEX) rc += " Label";
+ if (item.bare_id < App.LABEL_BASE_INDEX) rc += " Label";
return rc;
},
diff --git a/js/Headlines.js b/js/Headlines.js
index 1e6fc4268..b98098c33 100755
--- a/js/Headlines.js
+++ b/js/Headlines.js
@@ -1,7 +1,7 @@
'use strict';
-/* global __, ngettext, Article, App, escapeHtml */
-/* global xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Feeds */
+/* global __, ngettext, Article, App */
+/* global xhrPost, dojo, dijit, PluginHost, Notify, $$, Feeds */
/* global CommonDialogs */
const Headlines = {
@@ -402,7 +402,7 @@ const Headlines = {
if (headlines.vfeed_group_enabled) row_class += " vgrlf";
if (headlines.vfeed_group_enabled && hl.feed_title && this.vgroup_last_feed != hl.feed_id) {
- let vgrhdr = `
+ const vgrhdr = `
${hl.feed_icon}
${hl.feed_title}
done_all
@@ -426,9 +426,9 @@ const Headlines = {
id="RROW-${hl.id}"
data-article-id="${hl.id}"
data-orig-feed-id="${hl.feed_id}"
- data-content="${escapeHtml(hl.content)}"
+ data-content="${App.escapeHtml(hl.content)}"
data-score="${hl.score}"
- data-article-title="${escapeHtml(hl.title)}"
+ data-article-title="${App.escapeHtml(hl.title)}"
onmouseover="Article.mouseIn(${hl.id})"
onmouseout="Article.mouseOut(${hl.id})">
@@ -440,7 +440,7 @@ const Headlines = {
`;
@@ -685,7 +685,7 @@ const Headlines = {
console.log("no headlines received, infscroll_disabled=", Feeds.infscroll_disabled, 'first_id_changed=', first_id_changed);
- let hsp = $("headlines-spacer");
+ const hsp = $("headlines-spacer");
if (hsp) {
if (first_id_changed) {
@@ -1207,6 +1207,7 @@ const Headlines = {
}
},
onActionChanged: function (elem) {
+ // eslint-disable-next-line no-eval
eval(elem.value);
elem.attr('value', 'false');
},
diff --git a/js/common.js b/js/common.js
index 69b528a1c..c17e8bc45 100755
--- a/js/common.js
+++ b/js/common.js
@@ -1,21 +1,19 @@
-'use strict'
-/* global dijit, __ */
+'use strict';
-let LABEL_BASE_INDEX = -1024; /* not const because it's assigned at least once (by backend) */
-let loading_progress = 0;
+/* global dijit, __, App, Ajax */
/* error reporting shim */
-
// TODO: deprecated; remove
-function exception_error(e, e_compat, filename, lineno, colno) {
+/* function exception_error(e, e_compat, filename, lineno, colno) {
if (typeof e == "string")
e = e_compat;
App.Error.report(e, {filename: filename, lineno: lineno, colno: colno});
-}
+} */
/* xhr shorthand helpers */
+/* exported xhrPost */
function xhrPost(url, params, complete) {
console.log("xhrPost:", params);
@@ -31,6 +29,7 @@ function xhrPost(url, params, complete) {
});
}
+/* exported xhrJson */
function xhrJson(url, params, complete) {
return new Promise((resolve, reject) => {
return xhrPost(url, params).then((reply) => {
@@ -58,6 +57,7 @@ Array.prototype.remove = function(s) {
/* common helpers not worthy of separate Dojo modules */
+/* exported Lists */
const Lists = {
onRowChecked: function(elem) {
const checked = elem.domNode ? elem.attr("checked") : elem.checked;
@@ -87,7 +87,7 @@ const Lists = {
},
};
-// noinspection JSUnusedGlobalSymbols
+/* exported Tables */
const Tables = {
onRowChecked: function(elem) {
// account for dojo checkboxes
@@ -133,6 +133,7 @@ const Tables = {
}
};
+/* exported Cookie */
const Cookie = {
set: function (name, value, lifetime) {
const d = new Date();
@@ -152,12 +153,12 @@ const Cookie = {
},
delete: function(name) {
const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
- document.cookie = name + "=" + "" + "; " + expires;
+ document.cookie = name + "=; " + expires;
}
};
/* runtime notifications */
-
+/* exported Notify */
const Notify = {
KIND_GENERIC: 0,
KIND_INFO: 1,
@@ -237,30 +238,8 @@ const Notify = {
}
};
-// noinspection JSUnusedGlobalSymbols
-function displayIfChecked(checkbox, elemId) {
- if (checkbox.checked) {
- Effect.Appear(elemId, {duration : 0.5});
- } else {
- Effect.Fade(elemId, {duration : 0.5});
- }
-}
-
-/* function strip_tags(s) {
- return s.replace(/<\/?[^>]+(>|$)/g, "");
-} */
-
-// noinspection JSUnusedGlobalSymbols
-function label_to_feed_id(label) {
- return LABEL_BASE_INDEX - 1 - Math.abs(label);
-}
-
-// noinspection JSUnusedGlobalSymbols
-function feed_to_label_id(feed) {
- return LABEL_BASE_INDEX - 1 + Math.abs(feed);
-}
-
// http://stackoverflow.com/questions/6251937/how-to-get-selecteduser-highlighted-text-in-contenteditable-element-and-replac
+/* exported getSelectionText */
function getSelectionText() {
let text = "";
@@ -281,36 +260,3 @@ function getSelectionText() {
return text.stripTags();
}
-
-// noinspection JSUnusedGlobalSymbols
-function popupOpenUrl(url) {
- const w = window.open("");
-
- w.opener = null;
- w.location = url;
-}
-
-// noinspection JSUnusedGlobalSymbols
-function popupOpenArticle(id) {
- const w = window.open("",
- "ttrss_article_popup",
- "height=900,width=900,resizable=yes,status=no,location=no,menubar=no,directories=no,scrollbars=yes,toolbar=no");
-
- if (w) {
- w.opener = null;
- w.location = "backend.php?op=article&method=view&mode=raw&html=1&zoom=1&id=" + id + "&csrf_token=" + App.getInitParam("csrf_token");
- }
-}
-
-// htmlspecialchars()-alike for headlines data-content attribute
-function escapeHtml(text) {
- const map = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
-
- return text.replace(/[&<>"']/g, function(m) { return map[m]; });
-}