eslint-related fixes; move a few things from global context to App
This commit is contained in:
parent
88027d7a39
commit
d01ad09800
|
@ -91,7 +91,7 @@ module.exports = {
|
||||||
"max-statements-per-line": [ "warn", { "max" : 2 } ],
|
"max-statements-per-line": [ "warn", { "max" : 2 } ],
|
||||||
"multiline-comment-style": "off",
|
"multiline-comment-style": "off",
|
||||||
"multiline-ternary": "off",
|
"multiline-ternary": "off",
|
||||||
"new-cap": "error",
|
"new-cap": "warn",
|
||||||
"new-parens": "error",
|
"new-parens": "error",
|
||||||
"newline-after-var": "off",
|
"newline-after-var": "off",
|
||||||
"newline-before-return": "off",
|
"newline-before-return": "off",
|
||||||
|
@ -150,7 +150,7 @@ module.exports = {
|
||||||
"no-negated-condition": "off",
|
"no-negated-condition": "off",
|
||||||
"no-negated-in-lhs": "error",
|
"no-negated-in-lhs": "error",
|
||||||
"no-nested-ternary": "error",
|
"no-nested-ternary": "error",
|
||||||
"no-new": "error",
|
"no-new": "warn",
|
||||||
"no-new-func": "error",
|
"no-new-func": "error",
|
||||||
"no-new-object": "off",
|
"no-new-object": "off",
|
||||||
"no-new-require": "error",
|
"no-new-require": "error",
|
||||||
|
@ -162,7 +162,7 @@ module.exports = {
|
||||||
"no-process-env": "error",
|
"no-process-env": "error",
|
||||||
"no-process-exit": "error",
|
"no-process-exit": "error",
|
||||||
"no-proto": "error",
|
"no-proto": "error",
|
||||||
"no-prototype-builtins": "error",
|
"no-prototype-builtins": "warn",
|
||||||
"no-restricted-globals": "error",
|
"no-restricted-globals": "error",
|
||||||
"no-restricted-imports": "error",
|
"no-restricted-imports": "error",
|
||||||
"no-restricted-modules": "error",
|
"no-restricted-modules": "error",
|
||||||
|
|
|
@ -94,7 +94,7 @@ class Article extends Handler_Protected {
|
||||||
":id" => $ref_id];
|
":id" => $ref_id];
|
||||||
$sth->execute($params);
|
$sth->execute($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sth = $pdo->prepare("UPDATE ttrss_user_entries SET published = true,
|
$sth = $pdo->prepare("UPDATE ttrss_user_entries SET published = true,
|
||||||
last_published = NOW() WHERE
|
last_published = NOW() WHERE
|
||||||
int_id = ? AND owner_uid = ?");
|
int_id = ? AND owner_uid = ?");
|
||||||
|
@ -393,7 +393,7 @@ class Article extends Handler_Protected {
|
||||||
# $entry .= " <a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\" rel=\"noopener noreferrer\">" .
|
# $entry .= " <a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\" rel=\"noopener noreferrer\">" .
|
||||||
# $filename . " (" . $ctype . ")" . "</a>";
|
# $filename . " (" . $ctype . ")" . "</a>";
|
||||||
|
|
||||||
$entry = "<div onclick=\"popupOpenUrl('".htmlspecialchars($url)."')\"
|
$entry = "<div onclick=\"Article.popupOpenUrl('".htmlspecialchars($url)."')\"
|
||||||
dojoType=\"dijit.MenuItem\">$filename ($ctype)</div>";
|
dojoType=\"dijit.MenuItem\">$filename ($ctype)</div>";
|
||||||
|
|
||||||
array_push($entries_html, $entry);
|
array_push($entries_html, $entry);
|
||||||
|
@ -473,7 +473,7 @@ class Article extends Handler_Protected {
|
||||||
else
|
else
|
||||||
$filename = "";
|
$filename = "";
|
||||||
|
|
||||||
$rv .= "<div onclick='popupOpenUrl(\"".htmlspecialchars($entry["url"])."\")'
|
$rv .= "<div onclick='Article.popupOpenUrl(\"".htmlspecialchars($entry["url"])."\")'
|
||||||
dojoType=\"dijit.MenuItem\">".$filename . $title."</div>";
|
dojoType=\"dijit.MenuItem\">".$filename . $title."</div>";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -583,7 +583,7 @@ class Article extends Handler_Protected {
|
||||||
|
|
||||||
return "<div class='article-note $note_class'>
|
return "<div class='article-note $note_class'>
|
||||||
<i class='material-icons'>note</i>
|
<i class='material-icons'>note</i>
|
||||||
<div $onclick class='body'>$note</div>
|
<div $onclick class='body'>$note</div>
|
||||||
</div>";
|
</div>";
|
||||||
|
|
||||||
return $str;
|
return $str;
|
||||||
|
|
|
@ -701,12 +701,12 @@ class Feeds extends Handler_Protected {
|
||||||
print "<section>";
|
print "<section>";
|
||||||
print "<label>
|
print "<label>
|
||||||
<label class='checkbox'><input type='checkbox' name='need_auth' dojoType='dijit.form.CheckBox' id='feedDlg_loginCheck'
|
<label class='checkbox'><input type='checkbox' name='need_auth' dojoType='dijit.form.CheckBox' id='feedDlg_loginCheck'
|
||||||
onclick='displayIfChecked(this, \"feedDlg_loginContainer\")'>
|
onclick='App.displayIfChecked(this, \"feedDlg_loginContainer\")'>
|
||||||
".__('This feed requires authentication.')."</label>";
|
".__('This feed requires authentication.')."</label>";
|
||||||
print "</section>";
|
print "</section>";
|
||||||
|
|
||||||
print "<footer>";
|
print "<footer>";
|
||||||
print "<button dojoType='dijit.form.Button' class='alt-primary' type='submit'
|
print "<button dojoType='dijit.form.Button' class='alt-primary' type='submit'
|
||||||
onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>";
|
onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>";
|
||||||
|
|
||||||
print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button>";
|
print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button>";
|
||||||
|
@ -1337,7 +1337,7 @@ class Feeds extends Handler_Protected {
|
||||||
return 0;
|
return 0;
|
||||||
} else if ($cat == -2) {
|
} else if ($cat == -2) {
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT COUNT(DISTINCT article_id) AS unread
|
$sth = $pdo->prepare("SELECT COUNT(DISTINCT article_id) AS unread
|
||||||
FROM ttrss_user_entries ue, ttrss_user_labels2 l
|
FROM ttrss_user_entries ue, ttrss_user_labels2 l
|
||||||
WHERE article_id = ref_id AND unread IS true AND ue.owner_uid = :uid");
|
WHERE article_id = ref_id AND unread IS true AND ue.owner_uid = :uid");
|
||||||
$sth->execute(["uid" => $owner_uid]);
|
$sth->execute(["uid" => $owner_uid]);
|
||||||
|
@ -1373,8 +1373,8 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count
|
$sth = $pdo->prepare("SELECT SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count
|
||||||
FROM ttrss_user_entries ue
|
FROM ttrss_user_entries ue
|
||||||
WHERE ue.owner_uid = ?");
|
WHERE ue.owner_uid = ?");
|
||||||
|
|
||||||
$sth->execute([$user_id]);
|
$sth->execute([$user_id]);
|
||||||
|
@ -1468,7 +1468,7 @@ class Feeds extends Handler_Protected {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
if (DB_TYPE == "pgsql") {
|
||||||
$test_sth = $pdo->prepare("select $search_query_part
|
$test_sth = $pdo->prepare("select $search_query_part
|
||||||
FROM ttrss_entries, ttrss_user_entries WHERE id = ref_id limit 1");
|
FROM ttrss_entries, ttrss_user_entries WHERE id = ref_id limit 1");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -2272,9 +2272,9 @@ class Feeds extends Handler_Protected {
|
||||||
$label_id = Labels::find_id($commandpair[1], $_SESSION["uid"]);
|
$label_id = Labels::find_id($commandpair[1], $_SESSION["uid"]);
|
||||||
|
|
||||||
if ($label_id) {
|
if ($label_id) {
|
||||||
array_push($query_keywords, "($not
|
array_push($query_keywords, "($not
|
||||||
(ttrss_entries.id IN (
|
(ttrss_entries.id IN (
|
||||||
SELECT article_id FROM ttrss_user_labels2 WHERE
|
SELECT article_id FROM ttrss_user_labels2 WHERE
|
||||||
label_id = ".$pdo->quote($label_id).")))");
|
label_id = ".$pdo->quote($label_id).")))");
|
||||||
} else {
|
} else {
|
||||||
array_push($query_keywords, "(false)");
|
array_push($query_keywords, "(false)");
|
||||||
|
|
|
@ -554,7 +554,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$last_error = $row["last_error"];
|
$last_error = $row["last_error"];
|
||||||
|
|
||||||
if ($last_error) {
|
if ($last_error) {
|
||||||
print " <i class=\"material-icons\"
|
print " <i class=\"material-icons\"
|
||||||
title=\"".htmlspecialchars($last_error)."\">error</i>";
|
title=\"".htmlspecialchars($last_error)."\">error</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$auth_checked = $auth_enabled ? 'checked' : '';
|
$auth_checked = $auth_enabled ? 'checked' : '';
|
||||||
print "<label class='checkbox'>
|
print "<label class='checkbox'>
|
||||||
<input type='checkbox' $auth_checked name='need_auth' dojoType='dijit.form.CheckBox' id='feedEditDlg_loginCheck'
|
<input type='checkbox' $auth_checked name='need_auth' dojoType='dijit.form.CheckBox' id='feedEditDlg_loginCheck'
|
||||||
onclick='displayIfChecked(this, \"feedEditDlg_loginContainer\")'>
|
onclick='App.displayIfChecked(this, \"feedEditDlg_loginContainer\")'>
|
||||||
".__('This feed requires authentication.')."</label>";
|
".__('This feed requires authentication.')."</label>";
|
||||||
|
|
||||||
print '</div><div dojoType="dijit.layout.ContentPane" title="'.__('Options').'">';
|
print '</div><div dojoType="dijit.layout.ContentPane" title="'.__('Options').'">';
|
||||||
|
@ -1172,7 +1172,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
function index() {
|
function index() {
|
||||||
|
|
||||||
print "<div dojoType='dijit.layout.AccordionContainer' region='center'>";
|
print "<div dojoType='dijit.layout.AccordionContainer' region='center'>";
|
||||||
print "<div style='padding : 0px' dojoType='dijit.layout.AccordionPane'
|
print "<div style='padding : 0px' dojoType='dijit.layout.AccordionPane'
|
||||||
title=\"<i class='material-icons'>rss_feed</i> ".__('Feeds')."\">";
|
title=\"<i class='material-icons'>rss_feed</i> ".__('Feeds')."\">";
|
||||||
|
|
||||||
$sth = $this->pdo->prepare("SELECT COUNT(id) AS num_errors
|
$sth = $this->pdo->prepare("SELECT COUNT(id) AS num_errors
|
||||||
|
@ -1307,7 +1307,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
|
|
||||||
print "</div>"; # feeds pane
|
print "</div>"; # feeds pane
|
||||||
|
|
||||||
print "<div dojoType='dijit.layout.AccordionPane'
|
print "<div dojoType='dijit.layout.AccordionPane'
|
||||||
title='<i class=\"material-icons\">import_export</i> ".__('OPML')."'>";
|
title='<i class=\"material-icons\">import_export</i> ".__('OPML')."'>";
|
||||||
|
|
||||||
print "<h3>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . "</h3>";
|
print "<h3>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . "</h3>";
|
||||||
|
@ -1360,7 +1360,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
|
|
||||||
print "</div>"; # pane
|
print "</div>"; # pane
|
||||||
|
|
||||||
print "<div dojoType=\"dijit.layout.AccordionPane\"
|
print "<div dojoType=\"dijit.layout.AccordionPane\"
|
||||||
title=\"<i class='material-icons'>share</i> ".__('Published & shared articles / Generated feeds')."\">";
|
title=\"<i class='material-icons'>share</i> ".__('Published & shared articles / Generated feeds')."\">";
|
||||||
|
|
||||||
print "<h3>" . __('Published articles can be subscribed by anyone who knows the following URL:') . "</h3>";
|
print "<h3>" . __('Published articles can be subscribed by anyone who knows the following URL:') . "</h3>";
|
||||||
|
@ -1672,7 +1672,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
|
|
||||||
print "<fieldset class='narrow'>
|
print "<fieldset class='narrow'>
|
||||||
<label class='checkbox'><input type='checkbox' name='need_auth' dojoType='dijit.form.CheckBox'
|
<label class='checkbox'><input type='checkbox' name='need_auth' dojoType='dijit.form.CheckBox'
|
||||||
onclick='displayIfChecked(this, \"feedDlg_loginContainer\")'> ".
|
onclick='App.displayIfChecked(this, \"feedDlg_loginContainer\")'> ".
|
||||||
__('Feeds require authentication.')."</label></div>";
|
__('Feeds require authentication.')."</label></div>";
|
||||||
print "</fieldset>";
|
print "</fieldset>";
|
||||||
|
|
||||||
|
|
68
js/App.js
68
js/App.js
|
@ -1,8 +1,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global __, ngettext, Article, Headlines, Filters */
|
/* global __, Article, Ajax, Headlines, Filters */
|
||||||
/* global xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Feeds, Cookie */
|
/* global xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Feeds, Cookie */
|
||||||
/* global CommonDialogs, CommonFilters, Plugins */
|
/* global CommonDialogs, Plugins, Effect */
|
||||||
|
|
||||||
const App = {
|
const App = {
|
||||||
_initParams: [],
|
_initParams: [],
|
||||||
|
@ -12,8 +12,10 @@ const App = {
|
||||||
hotkey_prefix_timeout: 0,
|
hotkey_prefix_timeout: 0,
|
||||||
global_unread: -1,
|
global_unread: -1,
|
||||||
_widescreen_mode: false,
|
_widescreen_mode: false,
|
||||||
|
_loading_progress: 0,
|
||||||
hotkey_actions: {},
|
hotkey_actions: {},
|
||||||
is_prefs: false,
|
is_prefs: false,
|
||||||
|
LABEL_BASE_INDEX: -1024,
|
||||||
Scrollable: {
|
Scrollable: {
|
||||||
scrollByPages: function (elem, page_offset) {
|
scrollByPages: function (elem, page_offset) {
|
||||||
if (!elem) return;
|
if (!elem) return;
|
||||||
|
@ -46,8 +48,14 @@ const App = {
|
||||||
return elem.offsetTop + elem.offsetHeight <= ctr.scrollTop + ctr.offsetHeight &&
|
return elem.offsetTop + elem.offsetHeight <= ctr.scrollTop + ctr.offsetHeight &&
|
||||||
elem.offsetTop >= ctr.scrollTop;
|
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];
|
return this._initParams[k];
|
||||||
},
|
},
|
||||||
setInitParam: function(k, v) {
|
setInitParam: function(k, v) {
|
||||||
|
@ -130,12 +138,12 @@ const App = {
|
||||||
return this._rpc_seq;
|
return this._rpc_seq;
|
||||||
},
|
},
|
||||||
setLoadingProgress: function(p) {
|
setLoadingProgress: function(p) {
|
||||||
loading_progress += p;
|
this._loading_progress += p;
|
||||||
|
|
||||||
if (dijit.byId("loading_bar"))
|
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();
|
$("overlay").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +231,27 @@ const App = {
|
||||||
$$("#" + root + " *").each(function (i) {
|
$$("#" + root + " *").each(function (i) {
|
||||||
i.parentNode ? i.parentNode.removeChild(i) : true;
|
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);
|
const query = "backend.php?op=backend&method=help&topic=" + encodeURIComponent(topic);
|
||||||
|
|
||||||
if (dijit.byId("helpDlg"))
|
if (dijit.byId("helpDlg"))
|
||||||
|
@ -418,7 +445,7 @@ const App = {
|
||||||
if (params.hasOwnProperty(k)) {
|
if (params.hasOwnProperty(k)) {
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case "label_base_index":
|
case "label_base_index":
|
||||||
LABEL_BASE_INDEX = parseInt(params[k]);
|
this.LABEL_BASE_INDEX = parseInt(params[k]);
|
||||||
break;
|
break;
|
||||||
case "cdm_auto_catchup":
|
case "cdm_auto_catchup":
|
||||||
if (params[k] == 1) {
|
if (params[k] == 1) {
|
||||||
|
@ -429,16 +456,17 @@ const App = {
|
||||||
case "hotkeys":
|
case "hotkeys":
|
||||||
// filter mnemonic definitions (used for help panel) from hotkeys map
|
// filter mnemonic definitions (used for help panel) from hotkeys map
|
||||||
// i.e. *(191)|Ctrl-/ -> *(191)
|
// 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 = [];
|
params[k][1] = 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;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +615,7 @@ const App = {
|
||||||
['MutationObserver'].each(function(wf) {
|
['MutationObserver'].each(function(wf) {
|
||||||
if (!(wf in window)) {
|
if (!(wf in window)) {
|
||||||
errorMsg = `Browser feature check failed: <code>window.${wf}</code> not found.`;
|
errorMsg = `Browser feature check failed: <code>window.${wf}</code> not found.`;
|
||||||
throw $break;
|
throw new Error(errorMsg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict'
|
'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 = {
|
const Article = {
|
||||||
_scroll_reset_timeout: false,
|
_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) {
|
cdmUnsetActive: function (event) {
|
||||||
const row = $("RROW-" + Article.getActive());
|
const row = $("RROW-" + Article.getActive());
|
||||||
|
|
||||||
|
@ -157,14 +173,14 @@ const Article = {
|
||||||
comments_msg = hl.num_comments + " " + ngettext("comment", "comments", hl.num_comments)
|
comments_msg = hl.num_comments + " " + ngettext("comment", "comments", hl.num_comments)
|
||||||
}
|
}
|
||||||
|
|
||||||
comments = `<a href="${escapeHtml(hl.comments ? hl.comments : hl.link)}">(${comments_msg})</a>`;
|
comments = `<a href="${App.escapeHtml(hl.comments ? hl.comments : hl.link)}">(${comments_msg})</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return comments;
|
return comments;
|
||||||
},
|
},
|
||||||
formatOriginallyFrom: function(hl) {
|
formatOriginallyFrom: function(hl) {
|
||||||
return hl.orig_feed ? `<span>
|
return hl.orig_feed ? `<span>
|
||||||
${__('Originally from:')} <a target="_blank" rel="noopener noreferrer" href="${escapeHtml(hl.orig_feed[1])}">${hl.orig_feed[0]}</a>
|
${__('Originally from:')} <a target="_blank" rel="noopener noreferrer" href="${App.escapeHtml(hl.orig_feed[1])}">${hl.orig_feed[0]}</a>
|
||||||
</span>` : "";
|
</span>` : "";
|
||||||
},
|
},
|
||||||
unpack: function(row) {
|
unpack: function(row) {
|
||||||
|
@ -213,8 +229,8 @@ const Article = {
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="title"><a target="_blank" rel="noopener noreferrer"
|
<div class="title"><a target="_blank" rel="noopener noreferrer"
|
||||||
title="${escapeHtml(hl.title)}"
|
title="${App.escapeHtml(hl.title)}"
|
||||||
href="${escapeHtml(hl.link)}">${hl.title}</a></div>
|
href="${App.escapeHtml(hl.link)}">${hl.title}</a></div>
|
||||||
<div class="date">${hl.updated_long}</div>
|
<div class="date">${hl.updated_long}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -46,18 +46,20 @@ const CommonDialogs = {
|
||||||
xhr.onload = function () {
|
xhr.onload = function () {
|
||||||
switch (parseInt(this.responseText)) {
|
switch (parseInt(this.responseText)) {
|
||||||
case 0:
|
case 0:
|
||||||
Notify.info("Upload complete.");
|
{
|
||||||
|
Notify.info("Upload complete.");
|
||||||
|
|
||||||
if (App.isPrefs())
|
if (App.isPrefs())
|
||||||
dijit.byId("feedTree").reload();
|
dijit.byId("feedTree").reload();
|
||||||
else
|
else
|
||||||
Feeds.reload();
|
Feeds.reload();
|
||||||
|
|
||||||
const icon = $$(".feed-editor-icon")[0];
|
const icon = $$(".feed-editor-icon")[0];
|
||||||
|
|
||||||
if (icon)
|
if (icon)
|
||||||
icon.src = icon.src.replace(/\?[0-9]+$/, "?" + new Date().getTime());
|
icon.src = icon.src.replace(/\?[0-9]+$/, "?" + new Date().getTime());
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Notify.error("Upload failed: icon is too big.");
|
Notify.error("Upload failed: icon is too big.");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/* global __, ngettext, App, Article, Lists */
|
/* global __, App, Article, Lists, Effect */
|
||||||
/* global xhrPost, xhrJson, dojo, dijit, Notify, $$, Feeds */
|
/* global xhrPost, dojo, dijit, Notify, $$, Feeds */
|
||||||
|
|
||||||
const Filters = {
|
const Filters = {
|
||||||
filterDlgCheckAction: function(sender) {
|
filterDlgCheckAction: function(sender) {
|
||||||
|
@ -337,6 +337,7 @@ const Filters = {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!App.isPrefs()) {
|
if (!App.isPrefs()) {
|
||||||
|
/* global getSelectionText */
|
||||||
const selectedText = getSelectionText();
|
const selectedText = getSelectionText();
|
||||||
|
|
||||||
const lh = dojo.connect(dialog, "onLoad", function () {
|
const lh = dojo.connect(dialog, "onLoad", function () {
|
||||||
|
|
|
@ -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) {
|
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 id = args.item.id[0];
|
||||||
const bare_id = parseInt(id.substr(id.indexOf(':')+1));
|
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 label = dojo.create('i', { className: "material-icons icon icon-label", innerHTML: "label" });
|
||||||
|
|
||||||
//const fg_color = args.item.fg_color[0];
|
//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.auxcounter > 0) rc += " Has_Aux";
|
||||||
if (item.markedcounter > 0) rc += " Has_Marked";
|
if (item.markedcounter > 0) rc += " Has_Marked";
|
||||||
if (item.updates_disabled > 0) rc += " UpdatesDisabled";
|
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 == -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;
|
return rc;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global __, ngettext, Article, App, escapeHtml */
|
/* global __, ngettext, Article, App */
|
||||||
/* global xhrPost, xhrJson, dojo, dijit, PluginHost, Notify, $$, Feeds */
|
/* global xhrPost, dojo, dijit, PluginHost, Notify, $$, Feeds */
|
||||||
/* global CommonDialogs */
|
/* global CommonDialogs */
|
||||||
|
|
||||||
const Headlines = {
|
const Headlines = {
|
||||||
|
@ -402,7 +402,7 @@ const Headlines = {
|
||||||
if (headlines.vfeed_group_enabled) row_class += " vgrlf";
|
if (headlines.vfeed_group_enabled) row_class += " vgrlf";
|
||||||
|
|
||||||
if (headlines.vfeed_group_enabled && hl.feed_title && this.vgroup_last_feed != hl.feed_id) {
|
if (headlines.vfeed_group_enabled && hl.feed_title && this.vgroup_last_feed != hl.feed_id) {
|
||||||
let vgrhdr = `<div data-feed-id='${hl.feed_id}' class='feed-title'>
|
const vgrhdr = `<div data-feed-id='${hl.feed_id}' class='feed-title'>
|
||||||
<div style='float : right'>${hl.feed_icon}</div>
|
<div style='float : right'>${hl.feed_icon}</div>
|
||||||
<a class="title" href="#" onclick="Feeds.open({feed:${hl.feed_id}})">${hl.feed_title}
|
<a class="title" href="#" onclick="Feeds.open({feed:${hl.feed_id}})">${hl.feed_title}
|
||||||
<a class="catchup" title="${__('mark feed as read')}" onclick="Feeds.catchupFeedInGroup(${hl.feed_id})" href="#"><i class="icon-done material-icons">done_all</i></a>
|
<a class="catchup" title="${__('mark feed as read')}" onclick="Feeds.catchupFeedInGroup(${hl.feed_id})" href="#"><i class="icon-done material-icons">done_all</i></a>
|
||||||
|
@ -426,9 +426,9 @@ const Headlines = {
|
||||||
id="RROW-${hl.id}"
|
id="RROW-${hl.id}"
|
||||||
data-article-id="${hl.id}"
|
data-article-id="${hl.id}"
|
||||||
data-orig-feed-id="${hl.feed_id}"
|
data-orig-feed-id="${hl.feed_id}"
|
||||||
data-content="${escapeHtml(hl.content)}"
|
data-content="${App.escapeHtml(hl.content)}"
|
||||||
data-score="${hl.score}"
|
data-score="${hl.score}"
|
||||||
data-article-title="${escapeHtml(hl.title)}"
|
data-article-title="${App.escapeHtml(hl.title)}"
|
||||||
onmouseover="Article.mouseIn(${hl.id})"
|
onmouseover="Article.mouseIn(${hl.id})"
|
||||||
onmouseout="Article.mouseOut(${hl.id})">
|
onmouseout="Article.mouseOut(${hl.id})">
|
||||||
<div class="header-sticky-guard"></div>
|
<div class="header-sticky-guard"></div>
|
||||||
|
@ -440,7 +440,7 @@ const Headlines = {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span onclick="return Headlines.click(event, ${hl.id});" data-article-id="${hl.id}" class="titleWrap hlMenuAttach">
|
<span onclick="return Headlines.click(event, ${hl.id});" data-article-id="${hl.id}" class="titleWrap hlMenuAttach">
|
||||||
<a class="title" title="${escapeHtml(hl.title)}" target="_blank" rel="noopener noreferrer" href="${escapeHtml(hl.link)}">
|
<a class="title" title="${App.escapeHtml(hl.title)}" target="_blank" rel="noopener noreferrer" href="${App.escapeHtml(hl.link)}">
|
||||||
${hl.title}</a>
|
${hl.title}</a>
|
||||||
<span class="author">${hl.author}</span>
|
<span class="author">${hl.author}</span>
|
||||||
${hl.labels}
|
${hl.labels}
|
||||||
|
@ -457,7 +457,7 @@ const Headlines = {
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
|
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
|
||||||
|
|
||||||
<span style="cursor : pointer" title="${escapeHtml(hl.feed_title)}" onclick="Feeds.open({feed:${hl.feed_id}})">
|
<span style="cursor : pointer" title="${App.escapeHtml(hl.feed_title)}" onclick="Feeds.open({feed:${hl.feed_id}})">
|
||||||
${hl.feed_icon}</span>
|
${hl.feed_icon}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ const Headlines = {
|
||||||
data-orig-feed-id="${hl.feed_id}"
|
data-orig-feed-id="${hl.feed_id}"
|
||||||
data-article-id="${hl.id}"
|
data-article-id="${hl.id}"
|
||||||
data-score="${hl.score}"
|
data-score="${hl.score}"
|
||||||
data-article-title="${escapeHtml(hl.title)}"
|
data-article-title="${App.escapeHtml(hl.title)}"
|
||||||
onmouseover="Article.mouseIn(${hl.id})"
|
onmouseover="Article.mouseIn(${hl.id})"
|
||||||
onmouseout="Article.mouseOut(${hl.id})">
|
onmouseout="Article.mouseOut(${hl.id})">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
@ -507,7 +507,7 @@ const Headlines = {
|
||||||
</div>
|
</div>
|
||||||
<div onclick="return Headlines.click(event, ${hl.id})" class="title">
|
<div onclick="return Headlines.click(event, ${hl.id})" class="title">
|
||||||
<span data-article-id="${hl.id}" class="hl-content hlMenuAttach">
|
<span data-article-id="${hl.id}" class="hl-content hlMenuAttach">
|
||||||
<a class="title" href="${escapeHtml(hl.link)}">${hl.title} <span class="preview">${hl.content_preview}</span></a>
|
<a class="title" href="${App.escapeHtml(hl.link)}">${hl.title} <span class="preview">${hl.content_preview}</span></a>
|
||||||
<span class="author">${hl.author}</span>
|
<span class="author">${hl.author}</span>
|
||||||
${hl.labels}
|
${hl.labels}
|
||||||
</span>
|
</span>
|
||||||
|
@ -520,7 +520,7 @@ const Headlines = {
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
|
<i class="material-icons icon-score" title="${hl.score}" onclick="Article.setScore(${hl.id}, this)">${Article.getScorePic(hl.score)}</i>
|
||||||
<span onclick="Feeds.open({feed:${hl.feed_id}})" style="cursor : pointer" title="${escapeHtml(hl.feed_title)}">${hl.feed_icon}</span>
|
<span onclick="Feeds.open({feed:${hl.feed_id}})" style="cursor : pointer" title="${App.escapeHtml(hl.feed_title)}">${hl.feed_icon}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -685,7 +685,7 @@ const Headlines = {
|
||||||
|
|
||||||
console.log("no headlines received, infscroll_disabled=", Feeds.infscroll_disabled, 'first_id_changed=', first_id_changed);
|
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 (hsp) {
|
||||||
if (first_id_changed) {
|
if (first_id_changed) {
|
||||||
|
@ -1207,6 +1207,7 @@ const Headlines = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onActionChanged: function (elem) {
|
onActionChanged: function (elem) {
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
eval(elem.value);
|
eval(elem.value);
|
||||||
elem.attr('value', 'false');
|
elem.attr('value', 'false');
|
||||||
},
|
},
|
||||||
|
|
78
js/common.js
78
js/common.js
|
@ -1,21 +1,19 @@
|
||||||
'use strict'
|
'use strict';
|
||||||
/* global dijit, __ */
|
|
||||||
|
|
||||||
let LABEL_BASE_INDEX = -1024; /* not const because it's assigned at least once (by backend) */
|
/* global dijit, __, App, Ajax */
|
||||||
let loading_progress = 0;
|
|
||||||
|
|
||||||
/* error reporting shim */
|
/* error reporting shim */
|
||||||
|
|
||||||
// TODO: deprecated; remove
|
// 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")
|
if (typeof e == "string")
|
||||||
e = e_compat;
|
e = e_compat;
|
||||||
|
|
||||||
App.Error.report(e, {filename: filename, lineno: lineno, colno: colno});
|
App.Error.report(e, {filename: filename, lineno: lineno, colno: colno});
|
||||||
}
|
} */
|
||||||
|
|
||||||
/* xhr shorthand helpers */
|
/* xhr shorthand helpers */
|
||||||
|
|
||||||
|
/* exported xhrPost */
|
||||||
function xhrPost(url, params, complete) {
|
function xhrPost(url, params, complete) {
|
||||||
console.log("xhrPost:", params);
|
console.log("xhrPost:", params);
|
||||||
|
|
||||||
|
@ -31,6 +29,7 @@ function xhrPost(url, params, complete) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* exported xhrJson */
|
||||||
function xhrJson(url, params, complete) {
|
function xhrJson(url, params, complete) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
return xhrPost(url, params).then((reply) => {
|
return xhrPost(url, params).then((reply) => {
|
||||||
|
@ -58,6 +57,7 @@ Array.prototype.remove = function(s) {
|
||||||
|
|
||||||
/* common helpers not worthy of separate Dojo modules */
|
/* common helpers not worthy of separate Dojo modules */
|
||||||
|
|
||||||
|
/* exported Lists */
|
||||||
const Lists = {
|
const Lists = {
|
||||||
onRowChecked: function(elem) {
|
onRowChecked: function(elem) {
|
||||||
const checked = elem.domNode ? elem.attr("checked") : elem.checked;
|
const checked = elem.domNode ? elem.attr("checked") : elem.checked;
|
||||||
|
@ -87,7 +87,7 @@ const Lists = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
/* exported Tables */
|
||||||
const Tables = {
|
const Tables = {
|
||||||
onRowChecked: function(elem) {
|
onRowChecked: function(elem) {
|
||||||
// account for dojo checkboxes
|
// account for dojo checkboxes
|
||||||
|
@ -133,6 +133,7 @@ const Tables = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* exported Cookie */
|
||||||
const Cookie = {
|
const Cookie = {
|
||||||
set: function (name, value, lifetime) {
|
set: function (name, value, lifetime) {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
|
@ -152,12 +153,12 @@ const Cookie = {
|
||||||
},
|
},
|
||||||
delete: function(name) {
|
delete: function(name) {
|
||||||
const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||||
document.cookie = name + "=" + "" + "; " + expires;
|
document.cookie = name + "=; " + expires;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* runtime notifications */
|
/* runtime notifications */
|
||||||
|
/* exported Notify */
|
||||||
const Notify = {
|
const Notify = {
|
||||||
KIND_GENERIC: 0,
|
KIND_GENERIC: 0,
|
||||||
KIND_INFO: 1,
|
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
|
// http://stackoverflow.com/questions/6251937/how-to-get-selecteduser-highlighted-text-in-contenteditable-element-and-replac
|
||||||
|
/* exported getSelectionText */
|
||||||
function getSelectionText() {
|
function getSelectionText() {
|
||||||
let text = "";
|
let text = "";
|
||||||
|
|
||||||
|
@ -281,36 +260,3 @@ function getSelectionText() {
|
||||||
|
|
||||||
return text.stripTags();
|
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]; });
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue