summaryrefslogtreecommitdiff
path: root/p/scripts/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'p/scripts/main.js')
-rw-r--r--p/scripts/main.js2060
1 files changed, 963 insertions, 1097 deletions
diff --git a/p/scripts/main.js b/p/scripts/main.js
index 6cab2e55a..f59976b39 100644
--- a/p/scripts/main.js
+++ b/p/scripts/main.js
@@ -1,30 +1,61 @@
"use strict";
-/* globals $, jQuery, context, i18n, shortcut, shortcuts, url */
-/* jshint strict:global */
-
-var $stream = null,
- isCollapsed = true,
- shares = 0,
- ajax_loading = false;
-
-function redirect(url, new_tab) {
- if (url) {
- if (new_tab) {
- window.open(url);
- } else {
- location.href = url;
- }
+/* jshint esversion:6, strict:global */
+
+//<Polyfills>
+if (!NodeList.prototype.forEach) NodeList.prototype.forEach = Array.prototype.forEach;
+if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.webkitMatchesSelector;
+if (!Element.prototype.closest) Element.prototype.closest = function (s) {
+ let el = this;
+ do {
+ if (el.matches(s)) return el;
+ el = el.parentElement;
+ } while (el);
+ return null;
+ };
+if (!Element.prototype.remove) Element.prototype.remove = function () { if (this.parentNode) this.parentNode.removeChild(this); };
+//</Polyfills>
+
+//<Utils>
+function xmlHttpRequestJson(req) {
+ let json = req.response;
+ if (req.responseType !== 'json') { //IE11
+ try { json = JSON.parse(req.responseText); }
+ catch (ex) { json = null; }
}
+ return json;
}
+//</Utils>
+
+//<Global context>
+var context;
-function needsScroll($elem) {
- var $win = $(window),
- winTop = $win.scrollTop(),
- winHeight = $win.height(),
- winBottom = winTop + winHeight,
- elemTop = $elem.offset().top,
- elemBottom = elemTop + $elem.outerHeight();
- return (elemTop < winTop || elemBottom > winBottom) ? elemTop - (winHeight / 2) : 0;
+(function parseJsonVars() {
+ const jsonVars = document.getElementById('jsonVars'),
+ json = JSON.parse(jsonVars.innerHTML);
+ jsonVars.outerHTML = '';
+ context = json.context;
+ context.ajax_loading = false;
+ context.i18n = json.i18n;
+ context.shortcuts = json.shortcuts;
+ context.urls = json.urls;
+ context.icons = json.icons;
+ context.icons.read = decodeURIComponent(context.icons.read);
+ context.icons.unread = decodeURIComponent(context.icons.unread);
+}());
+//</Global context>
+
+function badAjax() {
+ openNotification(context.i18n.notif_request_failed, 'bad');
+ location.reload();
+ return true;
+}
+
+function needsScroll(elem) {
+ const winBottom = document.documentElement.scrollTop + document.documentElement.clientHeight,
+ elemTop = elem.offsetParent.offsetTop + elem.offsetTop,
+ elemBottom = elemTop + elem.offsetHeight;
+ return (elemTop < document.documentElement.scrollTop || elemBottom > winBottom) ?
+ elemTop - (document.documentElement.clientHeight / 2) : 0;
}
function str2int(str) {
@@ -40,10 +71,10 @@ function numberFormat(nStr) {
}
// http://www.mredkj.com/javascript/numberFormat.html
nStr += '';
- var x = nStr.split('.'),
- x1 = x[0],
+ const x = nStr.split('.'),
x2 = x.length > 1 ? '.' + x[1] : '',
rgx = /(\d+)(\d{3})/;
+ let x1 = x[0];
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ' ' + '$2');
}
@@ -51,29 +82,29 @@ function numberFormat(nStr) {
}
function incLabel(p, inc, spaceAfter) {
- var i = str2int(p) + inc;
+ const i = str2int(p) + inc;
return i > 0 ? ((spaceAfter ? '' : ' ') + '(' + numberFormat(i) + ')' + (spaceAfter ? ' ' : '')) : '';
}
function incUnreadsFeed(article, feed_id, nb) {
//Update unread: feed
- var elem = $('#' + feed_id).get(0),
+ let elem = document.getElementById(feed_id),
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0,
feed_priority = elem ? str2int(elem.getAttribute('data-priority')) : 0;
if (elem) {
elem.setAttribute('data-unread', feed_unreads + nb);
- elem = $(elem).children('.item-title').get(0);
+ elem = elem.querySelector('.item-title');
if (elem) {
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
}
}
//Update unread: category
- elem = $('#' + feed_id).parents('.category').get(0);
+ elem = document.getElementById(feed_id).closest('.category');
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
if (elem) {
elem.setAttribute('data-unread', feed_unreads + nb);
- elem = $(elem).find('.title').get(0);
+ elem = elem.querySelector('.title');
if (elem) {
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
}
@@ -81,7 +112,7 @@ function incUnreadsFeed(article, feed_id, nb) {
//Update unread: all
if (feed_priority > 0) {
- elem = $('#aside_feed .all .title').get(0);
+ elem = document.querySelector('#aside_feed .all .title');
if (elem) {
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
@@ -89,22 +120,22 @@ function incUnreadsFeed(article, feed_id, nb) {
}
//Update unread: favourites
- if (article && article.closest('div').hasClass('favorite')) {
- elem = $('#aside_feed .favorites .title').get(0);
+ if (article && article.closest('div').classList.contains('favorite')) {
+ elem = document.querySelector('#aside_feed .favorites .title');
if (elem) {
feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
elem.setAttribute('data-unread', numberFormat(feed_unreads + nb));
}
}
- var isCurrentView = false;
+ let isCurrentView = false;
// Update unread: title
document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)/, function (m, p1) {
- var $feed = $('#' + feed_id);
- if (article || ($feed.closest('.active').length > 0 && $feed.siblings('.active').length === 0)) {
+ const feed = document.getElementById(feed_id);
+ if (article || feed.closest('.active')) {
isCurrentView = true;
return incLabel(p1, nb, true);
- } else if ($('.all.active').length > 0) {
+ } else if (document.querySelector('.all.active')) {
isCurrentView = feed_priority > 0;
return incLabel(p1, feed_priority > 0 ? nb : 0, true);
} else {
@@ -115,126 +146,191 @@ function incUnreadsFeed(article, feed_id, nb) {
}
function incUnreadsTag(tag_id, nb) {
- var $t = $('#t_' + tag_id);
- var unreads = str2int($t.attr('data-unread'));
- $t.attr('data-unread', unreads + nb)
- .children('.item-title').attr('data-unread', numberFormat(unreads + nb));
-
- $t = $('.category.tags').find('.title');
- unreads = str2int($t.attr('data-unread'));
- $t.attr('data-unread', numberFormat(unreads + nb));
-}
-
-var pending_entries = {};
-function mark_read(active, only_not_read) {
- if ((active.length === 0) || (!active.attr('id')) ||
- context.anonymous ||
- (only_not_read && !active.hasClass("not_read"))) {
- return false;
+ let t = document.getElementById(tag_id);
+ if (t) {
+ let unreads = str2int(t.getAttribute('data-unread'));
+ t.setAttribute('data-unread', unreads + nb);
+ t.querySelector('.item-title').setAttribute('data-unread', numberFormat(unreads + nb));
}
-
- if (pending_entries[active.attr('id')]) {
- return false;
+ t = document.querySelector('.category.tags .title');
+ if (t) {
+ let unreads = str2int(t.getAttribute('data-unread'));
+ t.setAttribute('data-unread', numberFormat(unreads + nb));
}
- pending_entries[active.attr('id')] = true;
+}
- var url = '.?c=entry&a=read&id=' + active.attr('id').replace(/^flux_/, '') +
- (active.hasClass('not_read') ? '' : '&is_read=0');
+var pending_entries = {},
+ mark_read_queue = [];
- $.ajax({
- type: 'POST',
- url: url,
- data: {
+function send_mark_read_queue(queue, asRead, callback) {
+ const req = new XMLHttpRequest();
+ req.open('POST', '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'), true);
+ req.responseType = 'json';
+ req.onerror = function (e) {
+ openNotification(context.i18n.notif_request_failed, 'bad');
+ for (let i = queue.length - 1; i >= 0; i--) {
+ delete pending_entries['flux_' + queue[i]];
+ }
+ if (this.status == 403) {
+ badAjax();
+ }
+ };
+ req.onload = function (e) {
+ if (this.status != 200) {
+ return req.onerror(e);
+ }
+ const json = xmlHttpRequestJson(this);
+ for (let i = queue.length - 1; i >= 0; i--) {
+ const div = document.getElementById('flux_' + queue[i]),
+ myIcons = context.icons;
+ let inc = 0;
+ if (div.classList.contains('not_read')) {
+ div.classList.remove('not_read');
+ div.querySelectorAll('a.read').forEach(function (a) {
+ a.href = a.href.replace('&is_read=0', '') + '&is_read=1';
+ });
+ div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.read; });
+ inc--;
+ } else {
+ div.classList.add('not_read');
+ div.classList.add('keep_unread'); //Split for IE11
+ div.querySelectorAll('a.read').forEach(function (a) {
+ a.href = a.href.replace('&is_read=1', '');
+ });
+ div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.unread; });
+ inc++;
+ }
+ let feed_link = div.querySelector('.website > a, a.website');
+ if (feed_link) {
+ const feed_url = feed_link.href,
+ feed_id = feed_url.substr(feed_url.lastIndexOf('f_'));
+ incUnreadsFeed(div, feed_id, inc);
+ }
+ delete pending_entries['flux_' + queue[i]];
+ }
+ faviconNbUnread();
+ if (json.tags) {
+ const tagIds = Object.keys(json.tags);
+ for (let i = tagIds.length - 1; i >= 0; i--) {
+ let tagId = tagIds[i];
+ incUnreadsTag(tagId, (asRead ? -1 : 1) * json.tags[tagId].length);
+ }
+ }
+ onScroll();
+ if (callback) {
+ callback();
+ }
+ };
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({
ajax: true,
_csrf: context.csrf,
- },
- }).done(function (data) {
- var $r = active.find("a.read").attr("href", data.url),
- inc = 0;
- if (active.hasClass("not_read")) {
- active.removeClass("not_read");
- inc--;
- } else {
- active.addClass("not_read");
- active.addClass("keep_unread");
- inc++;
- }
- $r.find('.icon').replaceWith(data.icon);
+ id: queue,
+ }));
+}
- var feed_url = active.find(".website>a").attr("href");
- if (feed_url) {
- var feed_id = feed_url.substr(feed_url.lastIndexOf('f_'));
- incUnreadsFeed(active, feed_id, inc);
- }
- faviconNbUnread();
+var send_mark_read_queue_timeout = 0;
- if (data.tags) {
- for (var i = data.tags.length - 1; i >= 0; i--) {
- incUnreadsTag(data.tags[i], inc);
- }
- }
+function send_mark_queue_tick(callback) {
+ send_mark_read_queue_timeout = 0;
+ const queue = mark_read_queue.slice(0);
+ mark_read_queue = [];
+ send_mark_read_queue(queue, true, callback);
+}
- delete pending_entries[active.attr('id')];
- }).fail(function (data) {
- openNotification(i18n.notif_request_failed, 'bad');
- delete pending_entries[active.attr('id')];
- });
+function delayedClick(a) {
+ if (a) {
+ send_mark_queue_tick(function () { a.click(); });
+ }
}
-function mark_favorite(active) {
- if (active.length === 0) {
+function mark_read(div, only_not_read) {
+ if (!div || !div.id || context.anonymous ||
+ (only_not_read && !div.classList.contains('not_read'))) {
+ return false;
+ }
+ if (pending_entries[div.id]) {
return false;
}
+ pending_entries[div.id] = true;
+
+ const asRead = div.classList.contains('not_read'),
+ entryId = div.id.replace(/^flux_/, '');
+ if (asRead) {
+ mark_read_queue.push(entryId);
+ if (send_mark_read_queue_timeout == 0) {
+ send_mark_read_queue_timeout = setTimeout(function () { send_mark_queue_tick(null); }, 1000);
+ }
+ } else {
+ const queue = [ entryId ];
+ send_mark_read_queue(queue, asRead);
+ }
+}
- var url = active.find("a.bookmark").attr("href");
- if (url === undefined) {
+function mark_favorite(div) {
+ if (!div) {
return false;
}
- if (pending_entries[active.attr('id')]) {
+ let a = div.querySelector('a.bookmark'),
+ url = a ? a.href : '';
+ if (!url) {
return false;
}
- pending_entries[active.attr('id')] = true;
- $.ajax({
- type: 'POST',
- url: url,
- data: {
- ajax: true,
- _csrf: context.csrf,
- },
- }).done(function (data) {
- var $b = active.find("a.bookmark").attr("href", data.url),
- inc = 0;
- if (active.hasClass("favorite")) {
- active.removeClass("favorite");
- inc--;
- } else {
- active.addClass("favorite").find('.bookmark');
- inc++;
- }
- $b.find('.icon').replaceWith(data.icon);
+ if (pending_entries[div.id]) {
+ return false;
+ }
+ pending_entries[div.id] = true;
+
+ const req = new XMLHttpRequest();
+ req.open('POST', url, true);
+ req.responseType = 'json';
+ req.onerror = function (e) {
+ openNotification(context.i18n.notif_request_failed, 'bad');
+ delete pending_entries[div.id];
+ if (this.status == 403) {
+ badAjax();
+ }
+ };
+ req.onload = function (e) {
+ if (this.status != 200) {
+ return req.onerror(e);
+ }
+ const json = xmlHttpRequestJson(this);
+ let inc = 0;
+ if (div.classList.contains('favorite')) {
+ div.classList.remove('favorite');
+ inc--;
+ } else {
+ div.classList.add('favorite');
+ inc++;
+ }
+ div.querySelectorAll('a.bookmark').forEach(function (a) { a.href = json.url; });
+ div.querySelectorAll('a.bookmark > .icon').forEach(function (img) { img.outerHTML = json.icon; });
- var favourites = $('#aside_feed .favorites .title').contents().last().get(0);
- if (favourites && favourites.textContent) {
- favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) {
- return incLabel(p1, inc, false);
- });
- }
+ const favourites = document.querySelector('#aside_feed .favorites .title');
+ if (favourites) {
+ favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) {
+ return incLabel(p1, inc, false);
+ });
+ }
- if (active.closest('div').hasClass('not_read')) {
- var elem = $('#aside_feed .favorites .title').get(0),
- feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
- if (elem) {
- elem.setAttribute('data-unread', numberFormat(feed_unreads + inc));
+ if (div.classList.contains('not_read')) {
+ const elem = document.querySelector('#aside_feed .favorites .title'),
+ feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
+ if (elem) {
+ elem.setAttribute('data-unread', numberFormat(feed_unreads + inc));
+ }
}
- }
- delete pending_entries[active.attr('id')];
- }).fail(function (data) {
- openNotification(i18n.notif_request_failed, 'bad');
- delete pending_entries[active.attr('id')];
- });
+ delete pending_entries[div.id];
+ };
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({
+ ajax: true,
+ _csrf: context.csrf,
+ }));
}
var freshrssOpenArticleEvent = document.createEvent('Event');
@@ -242,208 +338,198 @@ freshrssOpenArticleEvent.initEvent('freshrss:openArticle', true, true);
function toggleContent(new_active, old_active, skipping) {
// If skipping, move current without activating or marking as read
- if (new_active.length === 0) {
+ if (!new_active) {
return;
}
if (context.does_lazyload && !skipping) {
- new_active.find('img[data-original], iframe[data-original]').each(function () {
- this.setAttribute('src', this.getAttribute('data-original'));
- this.removeAttribute('data-original');
+ new_active.querySelectorAll('img[data-original], iframe[data-original]').forEach(function (el) {
+ el.src = el.getAttribute('data-original');
+ el.removeAttribute('data-original');
});
}
- if (old_active[0] !== new_active[0]) {
- if (isCollapsed && !skipping) { // BUG?: isCollapsed can only ever be true
- new_active.addClass("active");
+ if (old_active !== new_active) {
+ if (!skipping) {
+ new_active.classList.add('active');
}
- old_active.removeClass("active current");
- new_active.addClass("current");
- if (context.auto_remove_article && !old_active.hasClass('not_read') && !skipping) {
- auto_remove(old_active);
+ new_active.classList.add('current');
+ if (old_active) {
+ old_active.classList.remove('active');
+ old_active.classList.remove('current'); //Split for IE11
}
- } else { // collapse_entry calls toggleContent(flux_current, flux_current, false)
- new_active.toggleClass('active');
+ } else {
+ new_active.classList.toggle('active');
}
- var relative_move = context.current_view === 'global',
- box_to_move = $(relative_move ? "#panel" : "html,body");
+ const relative_move = context.current_view === 'global',
+ box_to_move = relative_move ? document.getElementById('panel') : document.documentElement;
if (context.sticky_post) {
- var prev_article = new_active.prevAll('.flux'),
- new_pos = new_active.offset().top,
- old_scroll = box_to_move.scrollTop();
+ let prev_article = new_active.previousElementSibling,
+ new_pos = new_active.offsetTop + document.documentElement.scrollTop,
+ old_scroll = box_to_move.scrollTop;
- if (prev_article.length > 0 && new_pos - prev_article.offset().top <= 150) {
- new_pos = prev_article.offset().top;
+ if (prev_article && new_active.offsetTop - prev_article.offsetTop <= 150) {
+ new_pos = prev_article.offsetTop;
if (relative_move) {
- new_pos -= box_to_move.offset().top;
+ new_pos -= box_to_move.offsetTop;
}
}
if (skipping) {
// when skipping, this feels more natural if it's not so near the top
- new_pos -= $(window).height() / 4;
+ new_pos -= document.body.clientHeight / 4;
}
- if (context.hide_posts) {
- if (relative_move) {
- new_pos += old_scroll;
- }
-
- new_active.children(".flux_content").first().each(function () {
- box_to_move.scrollTop(new_pos).scrollTop();
- });
- } else {
- if (relative_move) {
- new_pos += old_scroll;
- }
-
- box_to_move.scrollTop(new_pos).scrollTop();
+ if (relative_move) {
+ new_pos += old_scroll;
}
+ box_to_move.scrollTop = new_pos;
}
- if (new_active.hasClass('active') && !skipping) {
+ if (new_active.classList.contains('active') && !skipping) {
if (context.auto_mark_article) {
mark_read(new_active, true);
}
- new_active[0].dispatchEvent(freshrssOpenArticleEvent);
+ new_active.dispatchEvent(freshrssOpenArticleEvent);
}
+ onScroll();
}
-function auto_remove(element) {
- var p = element.prev();
- var n = element.next();
- if (p.hasClass('day') && n.hasClass('day')) {
- p.remove();
- }
- element.remove();
- $('#stream > .flux:not(.not_read):not(.active)').remove();
-}
-
-function prev_entry() {
- var old_active = $(".flux.current"),
- new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first");
- toggleContent(new_active, old_active, false);
-}
-
-function next_entry() {
- var old_active = $(".flux.current"),
- new_active = old_active.length === 0 ? $(".flux:first") : old_active.nextAll(".flux:first");
- toggleContent(new_active, old_active, false);
-
- if (new_active.nextAll().length < 3) {
- load_more_posts();
+function prev_entry(skipping) {
+ const old_active = document.querySelector('.flux.current');
+ let new_active = old_active;
+ if (new_active) {
+ do new_active = new_active.previousElementSibling;
+ while (new_active && !new_active.classList.contains('flux'));
+ if (!new_active) {
+ prev_feed();
+ }
+ } else {
+ new_active = document.querySelector('.flux');
}
+ toggleContent(new_active, old_active, skipping);
}
-function skip_prev_entry() {
- var old_active = $(".flux.current"),
- new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first");
- toggleContent(new_active, old_active, true);
-}
-
-function skip_next_entry() {
- var old_active = $(".flux.current"),
- new_active = old_active.length === 0 ? $(".flux:first") : old_active.nextAll(".flux:first");
- toggleContent(new_active, old_active, true);
-
- if (new_active.nextAll().length < 3) {
- load_more_posts();
+function next_entry(skipping) {
+ const old_active = document.querySelector('.flux.current');
+ let new_active = old_active;
+ if (new_active) {
+ do new_active = new_active.nextElementSibling;
+ while (new_active && !new_active.classList.contains('flux'));
+ if (!new_active) {
+ next_feed();
+ }
+ } else {
+ new_active = document.querySelector('.flux');
}
+ toggleContent(new_active, old_active, skipping);
}
function prev_feed() {
- var active_feed = $("#aside_feed .tree-folder-items .item.active");
- if (active_feed.length > 0) {
- active_feed.prevAll(':visible:first').find('a').each(function(){this.click();});
- } else {
+ let found = false;
+ const feeds = document.querySelectorAll('#aside_feed .feed');
+ for (let i = feeds.length - 1; i >= 0; i--) {
+ const feed = feeds[i];
+ if (found && getComputedStyle(feed).display !== 'none') {
+ delayedClick(feed.querySelector('a.item-title'));
+ break;
+ } else if (feed.classList.contains('active')) {
+ found = true;
+ }
+ }
+ if (!found) {
last_feed();
}
}
function next_feed() {
- var active_feed = $("#aside_feed .tree-folder-items .item.active");
- if (active_feed.length > 0) {
- active_feed.nextAll(':visible:first').find('a').each(function(){this.click();});
- } else {
+ let found = false;
+ const feeds = document.querySelectorAll('#aside_feed .feed');
+ for (let i = 0; i < feeds.length; i++) {
+ const feed = feeds[i];
+ if (found && getComputedStyle(feed).display !== 'none') {
+ delayedClick(feed.querySelector('a.item-title'));
+ break;
+ } else if (feed.classList.contains('active')) {
+ found = true;
+ }
+ }
+ if (!found) {
first_feed();
}
}
function first_feed() {
- var feed = $("#aside_feed .tree-folder-items.active .item:visible:first");
- if (feed.length > 0) {
- feed.find('a')[1].click();
- }
+ const a = document.querySelector('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title');
+ delayedClick(a);
}
function last_feed() {
- var feed = $("#aside_feed .tree-folder-items.active .item:visible:last");
- if (feed.length > 0) {
- feed.find('a')[1].click();
+ const links = document.querySelectorAll('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title');
+ if (links && links.length > 0) {
+ delayedClick(links[links.length - 1]);
}
}
function prev_category() {
- var active_cat = $("#aside_feed .tree-folder.active");
-
- if (active_cat.length > 0) {
- var prev_cat = active_cat.prevAll(':visible:first').find('.tree-folder-title .title');
- if (prev_cat.length > 0) {
- prev_cat[0].click();
+ const active_cat = document.querySelector('#aside_feed .category.active');
+ if (active_cat) {
+ let cat = active_cat;
+ do cat = cat.previousElementSibling;
+ while (cat && getComputedStyle(cat).display === 'none');
+ if (cat) {
+ delayedClick(cat.querySelector('a.title'));
}
} else {
last_category();
}
- return;
}
function next_category() {
- var active_cat = $("#aside_feed .tree-folder.active");
-
- if (active_cat.length > 0) {
- var next_cat = active_cat.nextAll(':visible:first').find('.tree-folder-title .title');
- if (next_cat.length > 0) {
- next_cat[0].click();
+ const active_cat = document.querySelector('#aside_feed .category.active');
+ if (active_cat) {
+ let cat = active_cat;
+ do cat = cat.nextElementSibling;
+ while (cat && getComputedStyle(cat).display === 'none');
+ if (cat) {
+ delayedClick(cat.querySelector('a.title'));
}
} else {
first_category();
}
- return;
}
function first_category() {
- var cat = $("#aside_feed .tree-folder:visible:first");
- if (cat.length > 0) {
- cat.find('.tree-folder-title .title')[0].click();
- }
+ const a = document.querySelector('#aside_feed .category:not([data-unread="0"]) a.title');
+ delayedClick(a);
}
function last_category() {
- var cat = $("#aside_feed .tree-folder:visible:last");
- if (cat.length > 0) {
- cat.find('.tree-folder-title .title')[0].click();
+ const links = document.querySelectorAll('#aside_feed .category:not([data-unread="0"]) a.title');
+ if (links && links.length > 0) {
+ delayedClick(links[links.length - 1]);
}
}
function collapse_entry() {
- var flux_current = $(".flux.current");
+ const flux_current = document.querySelector('.flux.current');
toggleContent(flux_current, flux_current, false);
}
function user_filter(key) {
- var filter = $('#dropdown-query');
- var filters = filter.siblings('.dropdown-menu').find('.item.query a');
- if (typeof key === "undefined") {
- if (!filter.length) {
+ const filter = document.getElementById('dropdown-query'),
+ filters = filter.parentElement.querySelectorAll('.dropdown-menu > .query > a');
+ if (typeof key === 'undefined') {
+ if (!filters.length) {
return;
}
// Display the filter div
- window.location.hash = filter.attr('id');
+ location.hash = filter.id;
// Force scrolling to the filter div
- var scroll = needsScroll($('.header'));
+ const scroll = needsScroll(document.querySelector('.header'));
if (scroll !== 0) {
- $('html,body').scrollTop(scroll);
+ document.documentElement.scrollTop = scroll;
}
// Force the key value if there is only one action, so we can trigger it automatically
if (filters.length === 1) {
@@ -460,18 +546,18 @@ function user_filter(key) {
}
function auto_share(key) {
- var share = $(".flux.current.active").find('.dropdown-target[id^="dropdown-share"]');
- var shares = share.siblings('.dropdown-menu').find('.item a');
- if (typeof key === "undefined") {
- if (!share.length) {
- return;
- }
+ const share = document.querySelector('.flux.current.active .dropdown-target[id^="dropdown-share"]');
+ if (!share) {
+ return;
+ }
+ const shares = share.parentElement.querySelectorAll('.dropdown-menu .item a');
+ if (typeof key === 'undefined') {
// Display the share div
- window.location.hash = share.attr('id');
+ location.hash = share.id;
// Force scrolling to the share div
- var scroll = needsScroll(share.closest('.bottom'));
- if (scroll !== 0) {
- $('html,body').scrollTop(scroll);
+ const scrollTop = needsScroll(share.closest('.bottom'));
+ if (scrollTop !== 0) {
+ document.documentElement.scrollTop = scrollTop;
}
// Force the key value if there is only one action, so we can trigger it automatically
if (shares.length === 1) {
@@ -484,52 +570,70 @@ function auto_share(key) {
key = parseInt(key);
if (key <= shares.length) {
shares[key - 1].click();
- share.siblings('.dropdown-menu').find('.dropdown-close a')[0].click();
+ share.parentElement.querySelector('.dropdown-menu .dropdown-close a').click();
}
}
-function scrollAsRead(box_to_follow) {
- var minTop = 40 + (context.current_view === 'global' ? box_to_follow.offset().top : box_to_follow.scrollTop());
- $('.not_read:not(.keep_unread):visible').each(function () {
- var $this = $(this);
- if ($this.offset().top + $this.height() < minTop) {
- mark_read($this, true);
- }
- });
+var box_to_follow;
+
+function onScroll() {
+ if (!box_to_follow) {
+ return;
+ }
+ if (context.auto_mark_scroll) {
+ const minTop = 40 + box_to_follow.scrollTop;
+ document.querySelectorAll('.not_read:not(.keep_unread)').forEach(function (div) {
+ if (div.offsetHeight > 0 &&
+ div.offsetParent.offsetTop + div.offsetTop + div.offsetHeight < minTop) {
+ mark_read(div, true);
+ }
+ });
+ }
+ if (context.auto_remove_article) {
+ let maxTop = box_to_follow.scrollTop,
+ scrollOffset = 0;
+ document.querySelectorAll('.flux:not(.active):not(.keep_unread)').forEach(function (div) {
+ if (!pending_entries[div.id] && div.offsetHeight > 0 &&
+ div.offsetParent.offsetTop + div.offsetTop + div.offsetHeight < maxTop) {
+ const p = div.previousElementSibling,
+ n = div.nextElementSibling;
+ if (p && p.classList.contains('day') && n && n.classList.contains('day')) {
+ p.remove();
+ }
+ maxTop -= div.offsetHeight;
+ scrollOffset -= div.offsetHeight;
+ div.remove();
+ }
+ });
+ if (scrollOffset != 0) {
+ box_to_follow.scrollTop += scrollOffset;
+ return; //onscroll will be called again
+ }
+ }
+ if (context.auto_load_more) {
+ const pagination = document.getElementById('mark-read-pagination');
+ if (pagination && box_to_follow.offsetHeight > 0 &&
+ box_to_follow.scrollTop + box_to_follow.offsetHeight + (window.innerHeight / 2) >= pagination.offsetTop) {
+ load_more_posts();
+ }
+ }
}
function init_posts() {
- var box_to_follow = context.current_view === 'global' ? $("#panel") : $(window);
-
- if (context.auto_mark_scroll) {
- var lastScroll = 0, //Throttle
+ if (context.auto_load_more || context.auto_mark_scroll || context.auto_remove_article) {
+ box_to_follow = context.current_view === 'global' ? document.getElementById('panel') : document.documentElement;
+ let lastScroll = 0, //Throttle
timerId = 0;
- box_to_follow.scroll(function () {
- window.clearTimeout(timerId);
+ (box_to_follow === document.documentElement ? window : box_to_follow).onscroll = function () {
+ clearTimeout(timerId);
if (lastScroll + 500 < Date.now()) {
lastScroll = Date.now();
- scrollAsRead(box_to_follow);
+ onScroll();
} else {
- timerId = window.setTimeout(function() {
- scrollAsRead(box_to_follow);
- }, 500);
+ timerId = setTimeout(onScroll, 500);
}
- });
- }
-
- if (context.auto_load_more) {
- box_to_follow.scroll(function () {
- var load_more = $("#load_more");
- if (!load_more.is(':visible')) {
- return;
- }
- var boxBot = box_to_follow.scrollTop() + box_to_follow.height(),
- load_more_top = load_more.offset().top;
- if (boxBot >= load_more_top) {
- load_more_posts();
- }
- });
- box_to_follow.scroll();
+ };
+ onScroll();
}
}
@@ -538,482 +642,481 @@ function init_column_categories() {
return;
}
- $('#aside_feed').on('click', '.tree-folder>.tree-folder-title>a.dropdown-toggle', function () {
- $(this).children().each(function() {
- if (this.alt === '▽') {
- this.src = this.src.replace('/icons/down.', '/icons/up.');
- this.alt = '△';
+ document.getElementById('aside_feed').onclick = function (ev) {
+ let a = ev.target.closest('.tree-folder > .tree-folder-title > a.dropdown-toggle');
+ if (a) {
+ const img = a.querySelector('img');
+ if (img.alt === '▽') {
+ img.src = img.src.replace('/icons/down.', '/icons/up.');
+ img.alt = '△';
} else {
- this.src = this.src.replace('/icons/up.', '/icons/down.');
- this.alt = '▽';
+ img.src = img.src.replace('/icons/up.', '/icons/down.');
+ img.alt = '▽';
}
- });
- $(this).parent().next(".tree-folder-items").slideToggle(300, function () {
- //Workaround for Gecko bug 1514498 in Firefox 64
- var sidebar = document.getElementById('sidebar');
- if (sidebar && sidebar.scrollHeight > sidebar.clientHeight && //if needs scrollbar
- sidebar.scrollWidth >= sidebar.offsetWidth) { //but no scrollbar
- sidebar.style['overflow-y'] = 'scroll'; //then force scrollbar
- setTimeout(function () { sidebar.style['overflow-y'] = ''; }, 0);
+
+ const ul = a.closest('li').querySelector('.tree-folder-items');
+ let nbVisibleItems = 0;
+ for (let i = ul.children.length - 1; i >= 0; i--) {
+ if (ul.children[i].offsetHeight) {
+ nbVisibleItems++;
+ }
}
- });
- return false;
- });
+ ul.classList.toggle('active');
+ //CSS transition does not work on max-height:auto
+ ul.style.maxHeight = ul.classList.contains('active') ? (nbVisibleItems * 4) + 'em' : 0;
+ return false;
+ }
- $('#aside_feed').on('click', '.tree-folder-items .feed .dropdown-toggle', function () {
- var itemId = $(this).closest('.item').attr('id'),
- templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template',
- id = itemId.substr(2),
- feed_web = $(this).data('fweb'),
- template = $('#' + templateId)
- .html().replace(/------/g, id).replace('http://example.net/', feed_web);
- if ($(this).next('.dropdown-menu').length === 0) {
- $(this).attr('href', '#dropdown-' + id).prev('.dropdown-target').attr('id', 'dropdown-' + id).parent()
- .append(template).find('button.confirm').removeAttr('disabled');
- } else {
- if ($(this).next('.dropdown-menu').css('display') === 'none') {
- id = $(this).closest('.item').attr('id').substr(2);
- $(this).attr('href', '#dropdown-' + id);
+ a = ev.target.closest('.tree-folder-items > .feed .dropdown-toggle');
+ if (a) {
+ const itemId = a.closest('.item').id,
+ templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template',
+ id = itemId.substr(2),
+ feed_web = a.getAttribute('data-fweb'),
+ div = a.parentElement,
+ dropdownMenu = div.querySelector('.dropdown-menu'),
+ template = document.getElementById(templateId)
+ .innerHTML.replace(/------/g, id).replace('http://example.net/', feed_web);
+ if (!dropdownMenu) {
+ a.href = '#dropdown-' + id;
+ div.querySelector('.dropdown-target').id = 'dropdown-' + id;
+ div.insertAdjacentHTML('beforeend', template);
+ div.querySelector('button.confirm').disabled = false;
+ } else if (getComputedStyle(dropdownMenu).display === 'none') {
+ const id2 = div.closest('.item').id.substr(2);
+ a.href = '#dropdown-' + id2;
} else {
- $(this).attr('href', "#close");
+ a.href = '#close';
}
+ return true;
}
- });
+
+ return true;
+ };
}
function init_shortcuts() {
- if (!(window.shortcut && window.shortcuts)) {
- if (window.console) {
- console.log('FreshRSS waiting for shortcut.js…');
- }
- window.setTimeout(init_shortcuts, 200);
- return;
- }
- // Manipulation shortcuts
- shortcut.add(shortcuts.mark_read, function () {
- // Toggle the read state
- var active = $(".flux.current");
- mark_read(active, false);
- }, {
- 'disable_in_input': true
- });
- shortcut.add("shift+" + shortcuts.mark_read, function () {
- // Mark everything as read
- $(".nav_menu .read_all").click();
- }, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.mark_favorite, function () {
- // Toggle the favorite state
- var active = $(".flux.current");
- mark_favorite(active);
- }, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.collapse_entry, function () {
- // Toggle the collapse state
- collapse_entry();
- }, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.auto_share, function () {
- // Display the share options
- auto_share();
- }, {
- 'disable_in_input': true
- });
+ Object.keys(context.shortcuts).forEach(function (k) {
+ context.shortcuts[k] = (context.shortcuts[k] || '').toUpperCase();
+ });
- shortcut.add(shortcuts.user_filter, function () {
- // Display the user filters
- user_filter();
- }, {
- 'disable_in_input': true
- });
+ document.body.onkeydown = function (ev) {
+ if (ev.target.closest('input, textarea') ||
+ ev.ctrlKey || ev.metaKey || (ev.altKey && ev.shiftKey)) {
+ return true;
+ }
- function addShortcut(evt) {
- if ($('#dropdown-query').siblings('.dropdown-menu').is(':visible')) {
- user_filter(String.fromCharCode(evt.keyCode));
- } else {
- auto_share(String.fromCharCode(evt.keyCode));
- }
- }
- for (var i = 1; i < 10; i++) {
- shortcut.add(i.toString(), addShortcut, {
- 'disable_in_input': true
- });
- }
+ const s = context.shortcuts,
+ k = (ev.key.trim() || ev.code).toUpperCase();
+ if (location.hash.match(/^#dropdown-/)) {
+ const n = parseInt(k);
+ if (n) {
+ if (location.hash === '#dropdown-query') {
+ user_filter(n);
+ } else {
+ auto_share(n);
+ }
+ return false;
+ }
+ }
+ if (k === s.next_entry) {
+ if (ev.altKey) {
+ next_category();
+ } else if (ev.shiftKey) {
+ next_feed();
+ } else {
+ next_entry(false);
+ }
+ return false;
+ }
+ if (k === s.prev_entry) {
+ if (ev.altKey) {
+ prev_category();
+ } else if (ev.shiftKey) {
+ prev_feed();
+ } else {
+ prev_entry(false);
+ }
+ return false;
+ }
+ if (k === s.mark_read) {
+ if (ev.altKey) {
+ return true;
+ } else if (ev.shiftKey) { // Mark everything as read
+ document.querySelector('.nav_menu .read_all').click();
+ } else { // Toggle the read state
+ mark_read(document.querySelector('.flux.current'), false);
+ }
+ return false;
+ }
+ if (k === s.first_entry) {
+ if (ev.altKey) {
+ first_category();
+ } else if (ev.shiftKey) {
+ first_feed();
+ } else {
+ const old_active = document.querySelector('.flux.current'),
+ first = document.querySelector('.flux');
+ if (first.classList.contains('flux')) {
+ toggleContent(first, old_active, false);
+ }
+ }
+ return false;
+ }
+ if (k === s.last_entry) {
+ if (ev.altKey) {
+ last_category();
+ } else if (ev.shiftKey) {
+ last_feed();
+ } else {
+ const old_active = document.querySelector('.flux.current'),
+ last = document.querySelector('.flux:last-of-type');
+ if (last.classList.contains('flux')) {
+ toggleContent(last, old_active, false);
+ }
+ }
+ return false;
+ }
- // Entry navigation shortcuts
- shortcut.add(shortcuts.prev_entry, prev_entry, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.skip_prev_entry, skip_prev_entry, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.first_entry, function () {
- var old_active = $(".flux.current"),
- first = $(".flux:first");
+ if (ev.altKey || ev.shiftKey) {
+ return true;
+ }
+ if (k === s.mark_favorite) { // Toggle the favorite state
+ mark_favorite(document.querySelector('.flux.current'));
+ return false;
+ }
+ if (k === s.go_website) {
+ if (context.auto_mark_site) {
+ mark_read(document.querySelector('.flux.current'), true);
+ }
+ window.open(document.querySelector('.flux.current a.go_website').href);
+ return false;
+ }
+ if (k === s.skip_next_entry) { next_entry(true); return false; }
+ if (k === s.skip_prev_entry) { prev_entry(true); return false; }
+ if (k === s.collapse_entry) { collapse_entry(); return false; }
+ if (k === s.auto_share) { auto_share(); return false; }
+ if (k === s.user_filter) { user_filter(); return false; }
+ if (k === s.load_more) { load_more_posts(); return false; }
+ if (k === s.close_dropdown) { location.hash = null; return false; }
+ if (k === s.help) { window.open(context.urls.help); return false; }
+ if (k === s.focus_search) { document.getElementById('search').focus(); return false; }
+ if (k === s.normal_view) { delayedClick(document.querySelector('#nav_menu_views .view-normal')); return false; }
+ if (k === s.reading_view) { delayedClick(document.querySelector('#nav_menu_views .view-reader')); return false; }
+ if (k === s.global_view) { delayedClick(document.querySelector('#nav_menu_views .view-global')); return false; }
+ if (k === s.rss_view) { delayedClick(document.querySelector('#nav_menu_views .view-rss')); return false; }
+ return true;
+ };
+}
- if (first.hasClass("flux")) {
- toggleContent(first, old_active, false);
+function init_stream(stream) {
+ stream.onclick = function (ev) {
+ let el = ev.target.closest('.flux a.read');
+ if (el) {
+ mark_read(el.closest('.flux'), false);
+ return false;
}
- }, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.next_entry, next_entry, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.skip_next_entry, skip_next_entry, {
- 'disable_in_input': true
- });
- shortcut.add(shortcuts.last_entry, function () {
- var old_active = $(".flux.current"),
- last = $(".flux:last");
- if (last.hasClass("flux")) {
- toggleContent(last, old_active, false);
+ el = ev.target.closest('.flux a.bookmark');
+ if (el) {
+ mark_favorite(el.closest('.flux'));
+ return false;
}
- }, {
- 'disable_in_input': true
- });
- // Feed navigation shortcuts
- shortcut.add("shift+" + shortcuts.prev_entry, prev_feed, {
- 'disable_in_input': true
- });
- shortcut.add("shift+" + shortcuts.next_entry, next_feed, {
- 'disable_in_input': true
- });
- shortcut.add("shift+" + shortcuts.first_entry, first_feed, {
- 'disable_in_input': true
- });
- shortcut.add("shift+" + shortcuts.last_entry, last_feed, {
- 'disable_in_input': true
- });
- // Category navigation shortcuts
- shortcut.add("alt+" + shortcuts.prev_entry, prev_category, {
- 'disable_in_input': true
- });
- shortcut.add("alt+" + shortcuts.next_entry, next_category, {
- 'disable_in_input': true
- });
- shortcut.add("alt+" + shortcuts.first_entry, first_category, {
- 'disable_in_input': true
- });
- shortcut.add("alt+" + shortcuts.last_entry, last_category, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.go_website, function () {
- var url_website = $('.flux.current a.go_website').attr("href");
- if (context.auto_mark_site) {
- $(".flux.current").each(function () {
- mark_read($(this), true);
- });
+ el = ev.target.closest('.dynamictags');
+ if (el) {
+ loadDynamicTags(el);
+ return true;
}
- redirect(url_website, true);
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.load_more, function () {
- load_more_posts();
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.focus_search, function () {
- focus_search();
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.help, function () {
- redirect(url.help, true);
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.close_dropdown, function () {
- window.location.hash = null;
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.normal_view, function () {
- $('#nav_menu_views .view-normal').get(0).click();
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.global_view, function () {
- $('#nav_menu_views .view-global').get(0).click();
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.reading_view, function () {
- $('#nav_menu_views .view-reader').get(0).click();
- }, {
- 'disable_in_input': true
- });
-
- shortcut.add(shortcuts.rss_view, function () {
- $('#nav_menu_views .view-rss').get(0).click();
- }, {
- 'disable_in_input': true
- });
-}
-
-function init_stream(divStream) {
- divStream.on('click', '.flux_header,.flux_content', function (e) { //flux_toggle
- if ($(e.target).closest('.content, .item.website, .item.link, .dropdown-menu').length > 0) {
- return;
+ el = ev.target.closest('.item.title > a');
+ if (el) { // Allow default control-click behaviour such as open in backround-tab
+ return ev.ctrlKey;
}
- if (!context.sides_close_article && $(e.target).is('div.flux_content')) {
- // setting for not-closing after clicking outside article area
- return;
- }
- var old_active = $(".flux.current"),
- new_active = $(this).parent();
- isCollapsed = true;
- if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone
- if (context.auto_mark_article) {
- mark_read(new_active, true);
+
+ el = ev.target.closest('.flux .content a');
+ if (el) {
+ if (!el.closest('div').classList.contains('author')) {
+ el.target = '_blank';
+ el.rel = 'noreferrer';
}
return true;
}
- toggleContent(new_active, old_active, false);
- });
- divStream.on('click', '.flux a.read', function () {
- var active = $(this).parents(".flux");
- if (context.auto_remove_article && active.hasClass('not_read')) {
- auto_remove(active);
+ el = ev.target.closest('.item.share > a[href="#"]');
+ if (el) { //Print
+ const content = '<html><head><style>' +
+ 'body { font-family: Serif; text-align: justify; }' +
+ 'a { color: #000; text-decoration: none; }' +
+ 'a:after { content: " [" attr(href) "]"}' +
+ '</style></head><body>' +
+ el.closest('.flux_content').querySelector('.content').innerHTML +
+ '</body></html>';
+ const tmp_window = window.open();
+ tmp_window.document.writeln(content);
+ tmp_window.document.close();
+ tmp_window.focus();
+ tmp_window.print();
+ tmp_window.close();
+ return false;
}
- mark_read(active, false);
- return false;
- });
-
- divStream.on('click', '.flux a.bookmark', function () {
- var active = $(this).parents(".flux");
- mark_favorite(active);
- return false;
- });
- divStream.on('click', '.item.title > a', function (e) {
- // Allow default control-click behaviour such as open in backround-tab.
- return e.ctrlKey;
- });
- divStream.on('mouseup', '.item.title > a', function (e) {
- // Mouseup enables us to catch middle click.
- if (e.ctrlKey) {
- // CTRL+click, it will be manage by previous rule.
- return;
+ el = ev.target.closest('.item.share > a[href="POST"]');
+ if (el) { //Share by POST
+ const f = el.parentElement.querySelector('form');
+ f.disabled = false;
+ f.submit();
+ return false;
}
- if (e.which == 2) {
- // If middle click, we want same behaviour as CTRL+click.
- var ev = jQuery.Event("click");
- ev.ctrlKey = true;
- $(this).trigger(ev);
- } else if(e.which == 1) {
- // Normal click, just toggle article.
- $(this).parent().click();
+ el = ev.target.closest('.flux_header, .flux_content');
+ if (el) { //flux_toggle
+ if (ev.target.closest('.content, .item.website, .item.link, .dropdown-menu')) {
+ return true;
+ }
+ if (!context.sides_close_article && ev.target.matches('div.flux_content')) {
+ // setting for not-closing after clicking outside article area
+ return false;
+ }
+ const old_active = document.querySelector('.flux.current'),
+ new_active = el.parentNode;
+ if (ev.target.tagName.toUpperCase() === 'A') { //Leave real links alone
+ if (context.auto_mark_article) {
+ mark_read(new_active, true);
+ }
+ return true;
+ }
+ toggleContent(new_active, old_active, false);
+ return false;
}
- });
+ };
- divStream.on('click', '.flux .content a', function () {
- if (!$(this).closest('div').hasClass('author')) {
- $(this).attr('target', '_blank').attr('rel', 'noreferrer');
+ stream.onmouseup = function (ev) { // Mouseup enables us to catch middle click
+ let el = ev.target.closest('.item.title > a');
+ if (el) {
+ if (ev.ctrlKey) {
+ return; // CTRL+click, it will be manage by previous rule.
+ }
+ if (ev.which == 2) {
+ // If middle click, we want same behaviour as CTRL+click.
+ const evc = document.createEvent('click');
+ evc.ctrlKey = true;
+ el.dispatchEvent(evc);
+ } else if (ev.which == 1) {
+ // Normal click, just toggle article.
+ el.parentElement.click();
+ }
}
- });
- if (context.auto_mark_site) {
- // catch mouseup instead of click so we can have the correct behaviour
- // with middle button click (scroll button).
- divStream.on('mouseup', '.flux .link > a', function (e) {
- if (e.which == 3) {
- return;
+ if (context.auto_mark_site) {
+ // catch mouseup instead of click so we can have the correct behaviour
+ // with middle button click (scroll button).
+ el = ev.target.closest('.flux .link > a');
+ if (el) {
+ if (ev.which == 3) {
+ return;
+ }
+ mark_read(el.closest('.flux'), true);
}
+ }
+ };
- mark_read($(this).parents(".flux"), true);
- });
- }
+ stream.onchange = function (ev) {
+ const checkboxTag = ev.target.closest('.checkboxTag');
+ if (checkboxTag) { //Dynamic tags
+ ev.stopPropagation();
+ const isChecked = checkboxTag.checked,
+ tagId = checkboxTag.name.replace(/^t_/, ''),
+ tagName = checkboxTag.nextElementSibling ? checkboxTag.nextElementSibling.value : '',
+ entry = checkboxTag.closest('div.flux'),
+ entryId = entry.id.replace(/^flux_/, '');
+ checkboxTag.disabled = true;
+
+ const req = new XMLHttpRequest();
+ req.open('POST', './?c=tag&a=tagEntry', true);
+ req.responseType = 'json';
+ req.onerror = function (e) {
+ checkboxTag.checked = !isChecked;
+ if (this.status == 403) {
+ badAjax();
+ }
+ };
+ req.onload = function (e) {
+ if (this.status != 200) {
+ return req.onerror(e);
+ }
+ if (entry.classList.contains('not_read')) {
+ incUnreadsTag('t_' + tagId, isChecked ? 1 : -1);
+ }
+ };
+ req.onloadend = function (e) {
+ checkboxTag.disabled = false;
+ if (tagId == 0) {
+ loadDynamicTags(checkboxTag.closest('div.dropdown'));
+ }
+ };
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({
+ _csrf: context.csrf,
+ id_tag: tagId,
+ name_tag: tagId == 0 ? tagName : '',
+ id_entry: entryId,
+ checked: isChecked,
+ }));
+ }
+ };
}
-var $nav_entries = null;
-
function init_nav_entries() {
- $nav_entries = $('#nav_entries');
- $nav_entries.find('.previous_entry').click(function () {
- prev_entry();
- return false;
- });
- $nav_entries.find('.next_entry').click(function () {
- next_entry();
- return false;
- });
- $nav_entries.find('.up').click(function () {
- var active_item = $(".flux.current"),
- windowTop = $(window).scrollTop(),
- item_top = active_item.offset().top;
-
- if (windowTop > item_top) {
- $("html,body").scrollTop(item_top);
- } else {
- $("html,body").scrollTop(0);
- }
- return false;
- });
-}
+ const nav_entries = document.getElementById('nav_entries');
+ if (nav_entries) {
+ nav_entries.querySelector('.previous_entry').onclick = function (e) {
+ prev_entry(false);
+ return false;
+ };
+ nav_entries.querySelector('.next_entry').onclick = function (e) {
+ next_entry(false);
+ return false;
+ };
+ nav_entries.querySelector('.up').onclick = function (e) {
+ const active_item = document.querySelector('.flux.current'),
+ windowTop = document.documentElement.scrollTop,
+ item_top = active_item.offsetParent.offsetTop + active_item.offsetTop;
-function loadDynamicTags($div) {
- $div.removeClass('dynamictags');
- $div.find('li.item').remove();
- var entryId = $div.closest('div.flux').attr('id').replace(/^flux_/, '');
- $.getJSON('./?c=tag&a=getTagsForEntry&id_entry=' + entryId)
- .done(function (data) {
- var $ul = $div.find('.dropdown-menu');
- $ul.append('<li class="item"><label><input class="checkboxTag" name="t_0" type="checkbox" /> <input type="text" name="newTag" /></label></li>');
- if (data && data.length) {
- for (var i = 0; i < data.length; i++) {
- var tag = data[i];
- $ul.append('<li class="item"><label><input class="checkboxTag" name="t_' + tag.id + '" type="checkbox"' +
- (tag.checked ? ' checked="checked"' : '') + '> ' + tag.name + '</label></li>');
- }
- }
- })
- .fail(function () {
- $div.find('li.item').remove();
- $div.addClass('dynamictags');
- });
+ document.documentElement.scrollTop = windowTop > item_top ? item_top : 0;
+ return false;
+ };
+ }
}
-function init_dynamic_tags() {
- $stream.on('click', '.dynamictags', function () {
- loadDynamicTags($(this));
- });
+function loadDynamicTags(div) {
+ div.classList.remove('dynamictags');
+ div.querySelectorAll('li.item').forEach(function (li) { li.remove(); });
+ const entryId = div.closest('div.flux').id.replace(/^flux_/, '');
- $stream.on('change', '.checkboxTag', function (ev) {
- var $checkbox = $(this);
- $checkbox.prop('disabled', true);
- var isChecked = $checkbox.prop('checked');
- var tagId = $checkbox.attr('name').replace(/^t_/, '');
- var tagName = $checkbox.siblings('input[name]').val();
- var $entry = $checkbox.closest('div.flux');
- var entryId = $entry.attr('id').replace(/^flux_/, '');
- $.ajax({
- type: 'POST',
- url: './?c=tag&a=tagEntry',
- data: {
- _csrf: context.csrf,
- id_tag: tagId,
- name_tag: tagId == 0 ? tagName : '',
- id_entry: entryId,
- checked: isChecked,
- },
- })
- .done(function () {
- if ($entry.hasClass('not_read')) {
- incUnreadsTag(tagId, isChecked ? 1 : -1);
- }
- })
- .fail(function () {
- $checkbox.prop('checked', !isChecked);
- })
- .always(function () {
- $checkbox.prop('disabled', false);
- if (tagId == 0) {
- loadDynamicTags($checkbox.closest('div.dropdown'));
+ const req = new XMLHttpRequest();
+ req.open('GET', './?c=tag&a=getTagsForEntry&id_entry=' + entryId, true);
+ req.responseType = 'json';
+ req.onerror = function (e) {
+ div.querySelectorAll('li.item').forEach(function (li) { li.remove(); });
+ div.classList.add('dynamictags');
+ };
+ req.onload = function (e) {
+ if (this.status != 200) {
+ return req.onerror(e);
+ }
+ const json = xmlHttpRequestJson(this);
+ let html = '<li class="item"><label><input class="checkboxTag" name="t_0" type="checkbox" /> <input type="text" name="newTag" /></label></li>';
+ if (json && json.length) {
+ for (let i = 0; i < json.length; i++) {
+ const tag = json[i];
+ html += '<li class="item"><label><input class="checkboxTag" name="t_' + tag.id + '" type="checkbox"' +
+ (tag.checked ? ' checked="checked"' : '') + '> ' + tag.name + '</label></li>';
}
- });
- });
+ }
+ div.querySelector('.dropdown-menu').insertAdjacentHTML('beforeend', html);
+ };
+ req.send();
}
// <actualize>
var feed_processed = 0;
function updateFeed(feeds, feeds_count) {
- var feed = feeds.pop();
+ const feed = feeds.pop();
if (!feed) {
return;
}
- $.ajax({
- type: 'POST',
- url: feed.url,
- data: {
- _csrf: context.csrf,
- noCommit: 1,
- },
- }).always(function (data) {
- feed_processed++;
- $("#actualizeProgress .progress").html(feed_processed + " / " + feeds_count);
- $("#actualizeProgress .title").html(feed.title);
-
- if (feed_processed === feeds_count) {
- $.ajax({ //Empty request to commit new articles
- type: 'POST',
- url: './?c=feed&a=actualize&id=-1&ajax=1',
- data: {
+ const req = new XMLHttpRequest();
+ req.open('POST', feed.url, true);
+ req.onloadend = function (e) {
+ if (this.status != 200) {
+ return badAjax();
+ }
+ feed_processed++;
+ const div = document.getElementById('actualizeProgress');
+ div.querySelector('.progress').innerHTML = feed_processed + ' / ' + feeds_count;
+ div.querySelector('.title').innerHTML = feed.title;
+ if (feed_processed === feeds_count) {
+ //Empty request to commit new articles
+ const req2 = new XMLHttpRequest();
+ req2.open('POST', './?c=feed&a=actualize&id=-1&ajax=1', true);
+ req2.onloadend = function (e) {
+ location.reload();
+ };
+ req2.setRequestHeader('Content-Type', 'application/json');
+ req2.send(JSON.stringify({
_csrf: context.csrf,
noCommit: 0,
- },
- }).always(function (data) {
- window.location.reload();
- });
- } else {
- updateFeed(feeds, feeds_count);
- }
- });
+ }));
+ } else {
+ updateFeed(feeds, feeds_count);
+ }
+ };
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({
+ _csrf: context.csrf,
+ noCommit: 1,
+ }));
}
function init_actualize() {
- var auto = false;
+ let auto = false;
- $("#actualize").click(function () {
- if (ajax_loading) {
+ document.getElementById('actualize').onclick = function () {
+ if (context.ajax_loading) {
return false;
}
- ajax_loading = true;
-
- $.getJSON('./?c=javascript&a=actualize').done(function (data) {
- if (auto && data.feeds.length < 1) {
- auto = false;
- ajax_loading = false;
- return false;
- }
- if (data.feeds.length === 0) {
- openNotification(data.feedback_no_refresh, "good");
- $.ajax({ //Empty request to force refresh server database cache
- type: 'POST',
- url: './?c=feed&a=actualize&id=-1&ajax=1',
- data: {
- _csrf: context.csrf,
- noCommit: 0,
- },
- }).always(function (data) {
- ajax_loading = false;
- });
- return;
- }
- //Progress bar
- var feeds_count = data.feeds.length;
- $('body').after('<div id="actualizeProgress" class="notification good">' + data.feedback_actualize +
- '<br /><span class="title">/</span><br /><span class="progress">0 / ' + feeds_count +
- '</span></div>');
- for (var i = 10; i > 0; i--) {
- updateFeed(data.feeds, feeds_count);
- }
- });
+ context.ajax_loading = true;
+
+ const req = new XMLHttpRequest();
+ req.open('POST', './?c=javascript&a=actualize', true);
+ req.responseType = 'json';
+ req.onload = function (e) {
+ if (this.status != 200) {
+ return badAjax();
+ }
+ const json = xmlHttpRequestJson(this);
+ if (auto && json.feeds.length < 1) {
+ auto = false;
+ context.ajax_loading = false;
+ return false;
+ }
+ if (json.feeds.length === 0) {
+ openNotification(json.feedback_no_refresh, 'good');
+ //Empty request to commit new articles
+ const req2 = new XMLHttpRequest();
+ req2.open('POST', './?c=feed&a=actualize&id=-1&ajax=1', true);
+ req2.onloadend = function (e) {
+ context.ajax_loading = false;
+ };
+ req2.setRequestHeader('Content-Type', 'application/json');
+ req2.send(JSON.stringify({
+ _csrf: context.csrf,
+ noCommit: 0,
+ }));
+ return;
+ }
+ //Progress bar
+ const feeds_count = json.feeds.length;
+ document.body.insertAdjacentHTML('beforeend', '<div id="actualizeProgress" class="notification good">' +
+ json.feedback_actualize + '<br /><span class="title">/</span><br /><span class="progress">0 / ' +
+ feeds_count + '</span></div>');
+ for (let i = 10; i > 0; i--) {
+ updateFeed(json.feeds, feeds_count);
+ }
+ };
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({
+ _csrf: context.csrf,
+ }));
return false;
- });
+ };
if (context.auto_actualize_feeds) {
auto = true;
- $("#actualize").click();
+ document.getElementById('actualize').click();
}
}
// </actualize>
@@ -1027,39 +1130,31 @@ function openNotification(msg, status) {
if (notification_working === true) {
return false;
}
-
notification_working = true;
+ notification.querySelector('.msg').innerHTML = msg;
+ notification.className = 'notification';
+ notification.classList.add(status);
- notification.removeClass();
- notification.addClass("notification");
- notification.addClass(status);
- notification.find(".msg").html(msg);
- notification.fadeIn(300);
-
- notification_interval = window.setTimeout(closeNotification, 4000);
+ notification_interval = setTimeout(closeNotification, 4000);
}
function closeNotification() {
- notification.fadeOut(600, function() {
- notification.removeClass();
- notification.addClass('closed');
-
- window.clearInterval(notification_interval);
- notification_working = false;
- });
+ notification.classList.add('closed');
+ clearInterval(notification_interval);
+ notification_working = false;
}
function init_notifications() {
- notification = $("#notification");
+ notification = document.getElementById('notification');
- notification.find("a.close").click(function () {
- closeNotification();
- return false;
- });
+ notification.querySelector('a.close').onclick = function () {
+ closeNotification();
+ return false;
+ };
- if (notification.find(".msg").html().length > 0) {
+ if (notification.querySelector('.msg').innerHTML.length > 0) {
notification_working = true;
- notification_interval = window.setTimeout(closeNotification, 4000);
+ notification_interval = setTimeout(closeNotification, 4000);
}
}
// </notification>
@@ -1078,24 +1173,24 @@ function notifs_html5_ask_permission() {
}
function notifs_html5_show(nb) {
- if (notifs_html5_permission !== "granted") {
+ if (notifs_html5_permission !== 'granted') {
return;
}
- var notification = new window.Notification(i18n.notif_title_articles, {
- icon: "../themes/icons/favicon-256.png",
- body: i18n.notif_body_articles.replace('%d', nb),
- tag: "freshRssNewArticles"
+ const notification = new window.Notification(context.i18n.notif_title_articles, {
+ icon: '../themes/icons/favicon-256.png',
+ body: context.i18n.notif_body_articles.replace('%d', nb),
+ tag: 'freshRssNewArticles',
});
- notification.onclick = function() {
- window.location.reload();
+ notification.onclick = function () {
+ location.reload();
window.focus();
notification.close();
};
if (context.html5_notif_timeout !== 0) {
- setTimeout(function() {
+ setTimeout(function () {
notification.close();
}, context.html5_notif_timeout * 1000);
}
@@ -1111,84 +1206,117 @@ function init_notifs_html5() {
// </notifs html5>
function refreshUnreads() {
- $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) {
- var isAll = $('.category.all.active').length > 0,
- new_articles = false;
-
- $.each(data.feeds, function(feed_id, nbUnreads) {
- feed_id = 'f_' + feed_id;
- var elem = $('#' + feed_id).get(0),
- feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
-
- if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view?
- (nbUnreads - feed_unreads > 0)) {
- $('#new-article').attr('aria-hidden', 'false').show();
- new_articles = true;
- }
- });
+ const req = new XMLHttpRequest();
+ req.open('GET', './?c=javascript&a=nbUnreadsPerFeed', true);
+ req.responseType = 'json';
+ req.onload = function (e) {
+ const json = xmlHttpRequestJson(this);
+ const isAll = document.querySelector('.category.all.active');
+ let new_articles = false;
+
+ Object.keys(json.feeds).forEach(function (feed_id) {
+ const nbUnreads = json.feeds[feed_id];
+ feed_id = 'f_' + feed_id;
+ const elem = document.getElementById(feed_id),
+ feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0;
+
+ if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view?
+ (nbUnreads - feed_unreads > 0)) {
+ const newArticle = document.getElementById('new-article');
+ newArticle.setAttribute('aria-hidden', 'false');
+ newArticle.style.display = 'block';
+ new_articles = true;
+ }
+ });
- var nbUnreadTags = 0;
+ let nbUnreadTags = 0;
- $.each(data.tags, function(tag_id, nbUnreads) {
- nbUnreadTags += nbUnreads;
- $('#t_' + tag_id).attr('data-unread', nbUnreads)
- .children('.item-title').attr('data-unread', numberFormat(nbUnreads));
- });
+ Object.keys(json.tags).forEach(function (tag_id) {
+ const nbUnreads = json.tags[tag_id];
+ nbUnreadTags += nbUnreads;
+ const tag = document.getElementById('t_' + tag_id);
+ if (tag) {
+ tag.setAttribute('data-unread', nbUnreads);
+ tag.querySelector('.item-title').setAttribute('data-unread', numberFormat(nbUnreads));
+ }
+ });
- $('.category.tags').attr('data-unread', nbUnreadTags)
- .find('.title').attr('data-unread', numberFormat(nbUnreadTags));
+ const tags = document.querySelector('.category.tags');
+ if (tags) {
+ tags.setAttribute('data-unread', nbUnreadTags);
+ tags.querySelector('.title').setAttribute('data-unread', numberFormat(nbUnreadTags));
+ }
- var nb_unreads = str2int($('.category.all .title').attr('data-unread'));
+ const title = document.querySelector('.category.all .title'),
+ nb_unreads = title ? str2int(title.getAttribute('data-unread')) : 0;
- if (nb_unreads > 0 && new_articles) {
- faviconNbUnread(nb_unreads);
- notifs_html5_show(nb_unreads);
- }
- });
+ if (nb_unreads > 0 && new_articles) {
+ faviconNbUnread(nb_unreads);
+ notifs_html5_show(nb_unreads);
+ }
+ };
+ req.send();
}
//<endless_mode>
-var url_load_more = "",
+var url_load_more = '',
load_more = false,
box_load_more = null;
function load_more_posts() {
- if (load_more || url_load_more === '' || box_load_more === null) {
+ if (load_more || !url_load_more || !box_load_more) {
return;
}
-
load_more = true;
- $('#load_more').addClass('loading');
- $.get(url_load_more, function (data) {
- box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day'));
- $('.pagination').replaceWith($('.pagination', data));
- if (context.display_order === 'ASC') {
- $('#nav_menu_read_all .read_all').attr(
- 'formaction', $('#bigMarkAsRead').attr('formaction')
- );
- } else {
- $('#bigMarkAsRead').attr(
- 'formaction', $('#nav_menu_read_all .read_all').attr('formaction')
- );
- }
+ document.getElementById('load_more').classList.add('loading');
+
+ const req = new XMLHttpRequest();
+ req.open('GET', url_load_more, true);
+ req.responseType = 'document';
+ req.onload = function (e) {
+ const html = this.response,
+ formPagination = document.getElementById('mark-read-pagination');
+
+ const streamAdopted = document.adoptNode(html.getElementById('stream'));
+ streamAdopted.querySelectorAll('.flux, .day').forEach(function (div) {
+ box_load_more.insertBefore(div, formPagination);
+ });
+
+ const paginationOld = formPagination.querySelector('.pagination'),
+ paginationNew = streamAdopted.querySelector('.pagination');
+ formPagination.replaceChild(paginationNew, paginationOld);
- $('[id^=day_]').each(function (i) {
- var ids = $('[id="' + this.id + '"]');
- if (ids.length > 1) {
- $('[id="' + this.id + '"]:gt(0)').remove();
+ if (context.display_order === 'ASC') {
+ document.querySelector('#nav_menu_read_all .read_all').formAction =
+ document.getElementById('bigMarkAsRead').formAction;
+ } else {
+ const bigMarkAsRead = document.getElementById('bigMarkAsRead');
+ if (bigMarkAsRead) {
+ bigMarkAsRead.formAction = document.querySelector('#nav_menu_read_all .read_all').formAction;
+ }
}
- });
- init_load_more(box_load_more);
+ document.querySelectorAll('[id^=day_]').forEach(function (div) {
+ const ids = document.querySelectorAll('[id="' + div.id + '"]');
+ for (let i = ids.length - 1; i > 0; i--) { //Keep only the first
+ ids[i].remove();
+ }
+ });
- $('#load_more').removeClass('loading');
- $('#bigMarkAsRead').removeAttr('disabled');
- load_more = false;
- });
-}
+ init_load_more(box_load_more);
-function focus_search() {
- $('#search').focus();
+ const bigMarkAsRead = document.getElementById('bigMarkAsRead'),
+ div_load_more = document.getElementById('load_more');
+ if (bigMarkAsRead) {
+ bigMarkAsRead.removeAttribute('disabled');
+ }
+ if (div_load_more) {
+ div_load_more.classList.remove('loading');
+ }
+
+ load_more = false;
+ };
+ req.send();
}
var freshrssLoadMoreEvent = document.createEvent('Event');
@@ -1198,208 +1326,52 @@ function init_load_more(box) {
box_load_more = box;
document.body.dispatchEvent(freshrssLoadMoreEvent);
- var $next_link = $("#load_more");
- if (!$next_link.length) {
+ const next_link = document.getElementById('load_more');
+ if (!next_link) {
// no more article to load
- url_load_more = "";
+ url_load_more = '';
return;
}
- url_load_more = $next_link.attr("href");
+ url_load_more = next_link.href;
- $next_link.click(function () {
- load_more_posts();
- return false;
- });
+ next_link.onclick = function (e) {
+ load_more_posts();
+ return false;
+ };
}
//</endless_mode>
-//<crypto form (Web login)>
-function poormanSalt() { //If crypto.getRandomValues is not available
- var text = '$2a$04$',
- base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz';
- for (var i = 22; i > 0; i--) {
- text += base.charAt(Math.floor(Math.random() * 64));
- }
- return text;
-}
-
-function init_crypto_form() {
- /* globals dcodeIO */
- var $crypto_form = $('#crypto-form');
- if ($crypto_form.length === 0) {
- return;
- }
-
- if (!(window.dcodeIO)) {
- if (window.console) {
- console.log('FreshRSS waiting for bcrypt.js…');
- }
- window.setTimeout(init_crypto_form, 100);
- return;
- }
-
- $crypto_form.on('submit', function() {
- var $submit_button = $(this).find('button[type="submit"]');
- $submit_button.attr('disabled', '');
-
- var success = false;
- $.ajax({
- url: './?c=javascript&a=nonce&user=' + $('#username').val(),
- dataType: 'json',
- async: false
- }).done(function (data) {
- if (!data.salt1 || !data.nonce) {
- openNotification('Invalid user!', 'bad');
- } else {
- try {
- var strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'),
- s = dcodeIO.bcrypt.hashSync($('#passwordPlain').val(), data.salt1),
- c = dcodeIO.bcrypt.hashSync(data.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt());
- $('#challenge').val(c);
- if (!s || !c) {
- openNotification('Crypto error!', 'bad');
- } else {
- success = true;
- }
- } catch (e) {
- openNotification('Crypto exception! ' + e, 'bad');
+function init_confirm_action() {
+ document.body.onclick = function (ev) {
+ const b = ev.target.closest('.confirm');
+ if (b) {
+ let str_confirmation = this.getAttribute('data-str-confirm');
+ if (!str_confirmation) {
+ str_confirmation = context.i18n.confirmation_default;
}
+ return confirm(str_confirmation);
}
- }).fail(function() {
- openNotification('Communication error!', 'bad');
- });
-
- $submit_button.removeAttr('disabled');
- return success;
- });
-}
-//</crypto form (Web login)>
-
-function init_confirm_action() {
- $('body').on('click', '.confirm', function () {
- var str_confirmation = $(this).attr('data-str-confirm');
- if (!str_confirmation) {
- str_confirmation = i18n.confirmation_default;
- }
-
- return confirm(str_confirmation);
- });
- $('button.confirm').removeAttr('disabled');
-}
-
-function init_print_action() {
- $('.item.share > a[href="#"]').click(function (e) {
- var content = "<html><head><style>" +
- "body { font-family: Serif; text-align: justify; }" +
- "a { color: #000; text-decoration: none; }" +
- "a:after { content: ' [' attr(href) ']'}" +
- "</style></head><body>" +
- $(e.target).closest('.flux_content').find('.content').html() +
- "</body></html>";
-
- var tmp_window = window.open();
- tmp_window.document.writeln(content);
- tmp_window.document.close();
- tmp_window.focus();
- tmp_window.print();
- tmp_window.close();
-
- return false;
- });
-}
-
-function init_post_action() {
- $('.item.share > a[href="POST"]').click(function (event) {
- event.preventDefault();
- var form = $(this).next('form');
- $.post(form.data('url'), form.serialize());
- });
-}
-
-function init_share_observers() {
- shares = $('.group-share').length;
-
- $('.share.add').on('click', function(e) {
- var opt = $(this).siblings('select').find(':selected');
- var row = $(this).parents('form').data(opt.data('form'));
- row = row.replace(/##label##/g, opt.html().trim());
- row = row.replace(/##type##/g, opt.val());
- row = row.replace(/##help##/g, opt.data('help'));
- row = row.replace(/##key##/g, shares);
- row = row.replace(/##method##/g, opt.data('method'));
- row = row.replace(/##field##/g, opt.data('field'));
- $(this).parents('.form-group').before(row);
- shares++;
-
- return false;
- });
-}
-
-function init_stats_observers() {
- $('.select-change').on('change', function(e) {
- redirect($(this).find(':selected').data('url'));
- });
-}
-
-function init_remove_observers() {
- $('.post').on('click', 'a.remove', function(e) {
- var remove_what = $(this).attr('data-remove');
-
- if (remove_what !== undefined) {
- var remove_obj = $('#' + remove_what);
- remove_obj.remove();
- }
-
- return false;
- });
-}
-
-function init_feed_observers() {
- $('select[id="category"]').on('change', function() {
- var detail = $('#new_category_name').parent();
- if ($(this).val() === 'nc') {
- detail.attr('aria-hidden', 'false').show();
- detail.find('input').focus();
- } else {
- detail.attr('aria-hidden', 'true').hide();
- }
- });
-}
-
-function init_password_observers() {
- $('.toggle-password').on('mousedown', function(e) {
- var button = $(this);
- var passwordField = $('#' + button.attr('data-toggle'));
- passwordField.attr('type', 'text');
- button.addClass('active');
-
- return false;
- }).on('mouseup', function(e) {
- var button = $(this);
- var passwordField = $('#' + button.attr('data-toggle'));
- passwordField.attr('type', 'password');
- button.removeClass('active');
-
- return false;
- });
+ };
+ document.querySelectorAll('button.confirm').forEach(function (b) { b.disabled = false; });
}
function faviconNbUnread(n) {
if (typeof n === 'undefined') {
- n = str2int($('.category.all .title').attr('data-unread'));
+ const t = document.querySelector('.category.all .title');
+ n = t ? str2int(t.getAttribute('data-unread')) : 0;
}
//http://remysharp.com/2010/08/24/dynamic-favicons/
- var canvas = document.createElement('canvas'),
+ const canvas = document.createElement('canvas'),
link = document.getElementById('favicon').cloneNode(true);
if (canvas.getContext && link) {
canvas.height = canvas.width = 16;
- var img = document.createElement('img');
+ const img = document.createElement('img');
img.onload = function () {
- var ctx = canvas.getContext('2d');
+ const ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
if (n > 0) {
- var text = '';
+ let text = '';
if (n < 1000) {
text = n;
} else if (n < 100000) {
@@ -1414,167 +1386,61 @@ function faviconNbUnread(n) {
ctx.fillText(text, 0, canvas.height - 1);
}
link.href = canvas.toDataURL('image/png');
- $('link[rel~=icon]').remove();
+ document.querySelector('link[rel~=icon]').remove();
document.head.appendChild(link);
};
img.src = '../favicon.ico';
}
}
-function init_slider_observers() {
- var slider = $('#slider'),
- closer = $('#close-slider');
- if (slider.length < 1) {
- return;
- }
-
- $('.post').on('click', '.open-slider', function() {
- if (ajax_loading) {
- return false;
- }
-
- ajax_loading = true;
- var url_slide = $(this).attr('href');
-
- $.ajax({
- type: 'GET',
- url: url_slide,
- data: { ajax: true }
- }).done(function (data) {
- slider.html(data);
- closer.addClass('active');
- slider.addClass('active');
- ajax_loading = false;
- });
-
- return false;
- });
-
- closer.on('click', function() {
- closer.removeClass('active');
- slider.removeClass('active');
- return false;
- });
-}
-
-function init_configuration_alert() {
- $(window).on('submit', function(e) {
- window.hasSubmit = true;
- });
- $(window).on('beforeunload', function(e) {
- if (window.hasSubmit) {
- return;
- }
- var fields = $("[data-leave-validation]");
- for (var i = 0; i < fields.length; i++) {
- if ($(fields[i]).attr('type') === 'checkbox' || $(fields[i]).attr('type') === 'radio') {
- // The use of != is done on purpose to check boolean against integer
- if ($(fields[i]).is(':checked') != $(fields[i]).attr('data-leave-validation')) {
- return false;
- }
- } else {
- if ($(fields[i]).attr('data-leave-validation') !== $(fields[i]).val()) {
- return false;
- }
- }
- }
- return;
- });
-}
-
-function init_subscription() {
- $('body').on('click', '.bookmarkClick', function (e) {
- return false;
- });
-}
-
-function parseJsonVars() {
- var jsonVars = document.getElementById('jsonVars'),
- json = JSON.parse(jsonVars.innerHTML);
- jsonVars.outerHTML = '';
- window.context = json.context;
- window.shortcuts = json.shortcuts;
- window.url = json.url;
- window.i18n = json.i18n;
- window.icons = json.icons;
-}
-
function init_normal() {
- $stream = $('#stream');
- if ($stream.length < 1) {
+ const stream = document.getElementById('stream');
+ if (!stream) {
if (window.console) {
console.log('FreshRSS waiting for content…');
}
- window.setTimeout(init_normal, 100);
+ setTimeout(init_normal, 100);
return;
}
init_column_categories();
- init_stream($stream);
+ init_stream(stream);
init_shortcuts();
init_actualize();
faviconNbUnread();
}
function init_beforeDOM() {
- if (!window.$) {
- if (window.console) {
- console.log('FreshRSS waiting for jQuery…');
- }
- window.setTimeout(init_beforeDOM, 100);
- return;
- }
if (['normal', 'reader', 'global'].indexOf(context.current_view) >= 0) {
init_normal();
}
}
function init_afterDOM() {
- if (!window.$) {
- if (window.console) {
- console.log('FreshRSS waiting again for jQuery…');
- }
- window.setTimeout(init_afterDOM, 100);
- return;
- }
init_notifications();
init_confirm_action();
- $stream = $('#stream');
- if ($stream.length > 0) {
- init_load_more($stream);
+ const stream = document.getElementById('stream');
+ if (stream) {
+ init_load_more(stream);
init_posts();
init_nav_entries();
- init_dynamic_tags();
- init_print_action();
- init_post_action();
init_notifs_html5();
- window.setInterval(refreshUnreads, 120000);
- } else {
- init_subscription();
- init_crypto_form();
- init_share_observers();
- init_remove_observers();
- init_feed_observers();
- init_password_observers();
- init_stats_observers();
- init_slider_observers();
- init_configuration_alert();
+ setInterval(refreshUnreads, 120000);
}
if (window.console) {
- console.log('FreshRSS init done.');
+ console.log('FreshRSS main init done.');
}
}
-parseJsonVars();
init_beforeDOM(); //Can be called before DOM is fully loaded
if (document.readyState && document.readyState !== 'loading') {
init_afterDOM();
-} else if (document.addEventListener) {
+} else {
document.addEventListener('DOMContentLoaded', function () {
- if (window.console) {
- console.log('FreshRSS waiting for DOMContentLoaded…');
- }
- init_afterDOM();
- }, false);
+ if (window.console) {
+ console.log('FreshRSS waiting for DOMContentLoaded…');
+ }
+ init_afterDOM();
+ }, false);
}