summaryrefslogtreecommitdiff
path: root/public/scripts/main.js
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2013-11-03 19:22:59 +0100
committerGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2013-11-04 23:31:36 +0100
commit231516f5238b6023001bed548569077c61411a4e (patch)
tree2265c174152f3bc7c0fbe49f5a776bc4ca5c3020 /public/scripts/main.js
parentb23d66ec360208cf1e1d8ee2fc3bebf25997d9fa (diff)
Grosse optimisation JavaScript
* Fusion de endless_mode.js dans main.js car endless_mode.js est toujours chargé et assez petit. * Suppression des changements de style en JavaScript lors du chargement (genre boucle de .hide(), ou d'ajout de classe ".stick") et implémentation en PHP + CSS à la place. * Chargement JavaScript asynchrone (defer + async) pour de meilleurs performances. * Utilisation préférable des événements globaux plutôt que des événements pour chaque élément avec jQuery.on(events, selector) pour un chargement plus rapide et moins de mémoire utilisée. * Optimisation manuelle du JavaScript (sélecteurs CSS plus performants, méthodes jQuery plus appropriées, etc.). * Désactivation de init_img() qui était coûteux, lancé à un moment où les images ne sont de toute manière pas encore chargées, et qui n'apporte rien car il y a déjà un img {max-width:100%} en CSS. * JavaScript en mode strict. * Enfin, passage du code JavaScript dans JSLint et du coup nombreuses corrections (syntaxe, variables, méthodes dépréciées...). * Devrait permettre de fermer https://github.com/marienfressinaud/FreshRSS/issues/121 * Au passage, quelques simplifications CSS pour de meilleures performances.
Diffstat (limited to 'public/scripts/main.js')
-rw-r--r--public/scripts/main.js495
1 files changed, 260 insertions, 235 deletions
diff --git a/public/scripts/main.js b/public/scripts/main.js
index 684239568..92259696f 100644
--- a/public/scripts/main.js
+++ b/public/scripts/main.js
@@ -1,260 +1,248 @@
-function is_reader_mode() {
- var stream = $("#stream.reader");
- return stream.html() != null;
-}
+"use strict";
+var $stream = null;
function is_normal_mode() {
- var stream = $("#stream.normal");
- return stream.html() != null;
+ return $stream.hasClass('normal');
}
function is_global_mode() {
- var stream = $("#stream.global");
- return stream.html() != null;
+ return $stream.hasClass('global');
}
-function redirect (url, new_tab) {
+function redirect(url, new_tab) {
if (url) {
if (new_tab) {
- window.open (url);
+ window.open(url);
} else {
location.href = url;
}
}
}
-function toggleContent (new_active, old_active) {
- if (does_lazyload) {
- new_active.find('img[data-original]').each(function() {
- this.setAttribute('src', this.getAttribute('data-original'));
- this.removeAttribute('data-original');
- });
- }
-
- old_active.removeClass ("active");
- if (old_active[0] != new_active[0]) {
- new_active.addClass ("active");
- }
-
- var box_to_move = "html,body";
- var relative_move = false;
- if (is_global_mode()) {
- box_to_move = "#panel";
- relative_move = true;
- }
-
- var new_pos = new_active.position ().top,
- old_scroll = $(box_to_move).scrollTop (),
- new_scroll = old_scroll;
- if (hide_posts) {
- old_active.children (".flux_content").toggle (0);
-
- new_pos = new_active.position ().top;
- old_scroll = $(box_to_move).scrollTop ();
-
- if (relative_move) {
- new_pos += old_scroll;
- }
-
- if (old_active[0] != new_active[0]) {
- new_active.children (".flux_content").toggle (0, function () {
- new_scroll = $(box_to_move).scrollTop (new_pos).scrollTop ();
- });
- }
- } else {
- if (relative_move) {
- new_pos += old_scroll;
- }
-
- new_scroll = $(box_to_move).scrollTop (new_pos).scrollTop ();
- }
-
- if (auto_mark_article) {
- mark_read(new_active, true);
- }
-}
-
-function _incLabel(p, inc) {
- var i = (parseInt(p.replace(/\D/g, '')) || 0) + inc;
+function incLabel(p, inc) {
+ var i = (parseInt(p.replace(/\D/g, ''), 10) || 0) + inc;
return i > 0 ? ' (' + i + ')' : '';
}
-function mark_read (active, only_not_read) {
- if (active[0] === undefined || (
- only_not_read === true && !active.hasClass("not_read"))) {
+function mark_read(active, only_not_read) {
+ if (active[0] === undefined || (only_not_read === true && !active.hasClass("not_read"))) {
return false;
}
- url = active.find ("a.read").attr ("href");
+ var url = active.find("a.read").attr("href");
if (url === undefined) {
return false;
}
- $.ajax ({
+ $.ajax({
type: 'POST',
url: url,
data : { ajax: true }
- }).done (function (data) {
- res = jQuery.parseJSON(data);
+ }).done(function (data) {
+ var res = $.parseJSON(data);
- active.find ("a.read").attr ("href", res.url);
+ active.find("a.read").attr("href", res.url);
var inc = 0;
- if (active.hasClass ("not_read")) {
- active.removeClass ("not_read");
+ if (active.hasClass("not_read")) {
+ active.removeClass("not_read");
inc--;
} else if (only_not_read !== true || active.hasClass("not_read")) {
- active.addClass ("not_read");
+ active.addClass("not_read");
inc++;
}
- //Update unread: feed //Alex
+ //Update unread: feed
var feed_url = active.find(".website>a").attr("href"),
feed_id = feed_url.substr(feed_url.lastIndexOf('f_')),
elem = $('#' + feed_id + ' .feed').get(0),
- attr_unread = elem ? elem.getAttributeNode('data-unread') : null,
- feed_priority = elem ? parseInt(elem.getAttribute('data-priority')) : 0;
- if (attr_unread)
- attr_unread.value = Math.max(0, parseInt(attr_unread.value) + inc);
+ feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0,
+ feed_priority = elem ? (parseInt(elem.getAttribute('data-priority'), 10) || 0) : 0;
+ elem.setAttribute('data-unread', Math.max(0, feed_unread + inc));
//Update unread: category
elem = $('#' + feed_id).parent().prevAll('.category').children(':first').get(0);
- attr_unread = elem ? elem.getAttributeNode('data-unread') : null;
- if (attr_unread)
- attr_unread.value = Math.max(0, parseInt(attr_unread.value) + inc);
+ feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0;
+ elem.setAttribute('data-unread', Math.max(0, feed_unread + inc));
- if (feed_priority > 0) { //Update unread: all
+ //Update unread: all
+ if (feed_priority > 0) {
elem = $('#aside_flux .all').children(':first').get(0);
- attr_unread = elem ? elem.getAttributeNode('data-unread') : null;
- if (attr_unread)
- attr_unread.value = Math.max(0, parseInt(attr_unread.value) + inc);
+ feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0;
+ elem.setAttribute('data-unread', Math.max(0, feed_unread + inc));
}
//Update unread: title
- document.title = document.title.replace(/((?: \(\d+\))?)( - .*?)((?: \(\d+\))?)$/, function(m, p1, p2, p3) {
- return _incLabel(p1, inc) + p2 + _incLabel(p3, feed_priority > 0 ? inc : 0);
+ document.title = document.title.replace(/((?: \(\d+\))?)( - .*?)((?: \(\d+\))?)$/, function (m, p1, p2, p3) {
+ return incLabel(p1, inc) + p2 + incLabel(p3, feed_priority > 0 ? inc : 0);
});
});
}
-function mark_favorite (active) {
+function mark_favorite(active) {
if (active[0] === undefined) {
return false;
}
- url = active.find ("a.bookmark").attr ("href");
+ var url = active.find("a.bookmark").attr("href");
if (url === undefined) {
return false;
}
- $.ajax ({
+ $.ajax({
type: 'POST',
url: url,
data : { ajax: true }
- }).done (function (data) {
- res = jQuery.parseJSON(data);
+ }).done(function (data) {
+ var res = $.parseJSON(data);
- active.find ("a.bookmark").attr ("href", res.url);
+ active.find("a.bookmark").attr("href", res.url);
var inc = 0;
- if (active.hasClass ("favorite")) {
- active.removeClass ("favorite");
+ if (active.hasClass("favorite")) {
+ active.removeClass("favorite");
inc--;
} else {
- active.addClass ("favorite");
+ active.addClass("favorite");
inc++;
}
var favourites = $('.favorites>a').contents().last().get(0);
- if (favourites && favourites.textContent)
- favourites.textContent = favourites.textContent.replace(/((?: \(\d+\))?\s*)$/, function(m, p1) {
- return _incLabel(p1, inc);
+ if (favourites && favourites.textContent) {
+ favourites.textContent = favourites.textContent.replace(/((?: \(\d+\))?\s*)$/, function (m, p1) {
+ return incLabel(p1, inc);
});
+ }
});
}
+function toggleContent(new_active, old_active) {
+ if (does_lazyload) {
+ new_active.find('img[data-original]').each(function () {
+ this.setAttribute('src', this.getAttribute('data-original'));
+ this.removeAttribute('data-original');
+ });
+ }
+
+ old_active.removeClass("active");
+ if (old_active[0] !== new_active[0]) {
+ new_active.addClass("active");
+ }
+
+ var box_to_move = "html,body",
+ relative_move = false;
+ if (is_global_mode()) {
+ box_to_move = "#panel";
+ relative_move = true;
+ }
+
+ var new_pos = new_active.position().top,
+ old_scroll = $(box_to_move).scrollTop();
+ if (hide_posts) {
+
+ new_pos = new_active.position().top;
+ old_scroll = $(box_to_move).scrollTop();
+
+ if (relative_move) {
+ new_pos += old_scroll;
+ }
+
+ if (old_active[0] !== new_active[0]) {
+ 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 (auto_mark_article) {
+ mark_read(new_active, true);
+ }
+}
+
function prev_entry() {
- old_active = $(".flux.active");
- last_active = $(".flux:last");
- new_active = old_active.prevAll (".flux:first");
+ var old_active = $(".flux.active"),
+ last_active = $(".flux:last"),
+ new_active = old_active.prevAll(".flux:first");
if (new_active.hasClass("flux")) {
- toggleContent (new_active, old_active);
- } else if (old_active[0] === undefined &&
- new_active[0] === undefined) {
- toggleContent (last_active, old_active);
+ toggleContent(new_active, old_active);
+ } else if (old_active[0] === undefined && new_active[0] === undefined) {
+ toggleContent(last_active, old_active);
}
}
function next_entry() {
- old_active = $(".flux.active");
- first_active = $(".flux:first");
- last_active = $(".flux:last");
- new_active = old_active.nextAll (".flux:first");
+ var old_active = $(".flux.active"),
+ first_active = $(".flux:first"),
+ last_active = $(".flux:last"),
+ new_active = old_active.nextAll(".flux:first");
if (new_active.hasClass("flux")) {
- toggleContent (new_active, old_active);
- } else if (old_active[0] === undefined &&
- new_active[0] === undefined) {
- toggleContent (first_active, old_active);
+ toggleContent(new_active, old_active);
+ } else if (old_active[0] === undefined && new_active[0] === undefined) {
+ toggleContent(first_active, old_active);
}
if ((!auto_load_more) && (last_active.attr("id") === new_active.attr("id"))) {
- load_more_posts ();
+ load_more_posts();
}
}
-function init_img () {
+/*function init_img() {
var maxWidth = $(".flux_content .content").width() / 2;
- $(".flux_content .content img").each (function () {
- if ($(this).width () > maxWidth) {
+ $(".flux_content .content img").each(function () {
+ if ($(this).width() > maxWidth) {
$(this).addClass("big");
}
});
-}
+}*/
function inMarkViewport(flux, box_to_follow, relative_follow) {
var top = flux.position().top;
if (relative_follow) {
top += box_to_follow.scrollTop();
}
- var height = flux.height();
- var begin = top + 3 * height / 4;
- var bot = Math.min(begin + 75, top + height);
-
- var windowTop = box_to_follow.scrollTop();
- var windowBot = windowTop + box_to_follow.height() / 2;
+ var height = flux.height(),
+ begin = top + 3 * height / 4,
+ bot = Math.min(begin + 75, top + height),
+ windowTop = box_to_follow.scrollTop(),
+ windowBot = windowTop + box_to_follow.height() / 2;
return (windowBot >= begin && bot >= windowBot);
}
-function init_posts () {
- init_img ();
+function init_lazyload() {
if ($.fn.lazyload) {
if (is_global_mode()) {
- $(".flux .content img").lazyload({
+ $(".flux_content img").lazyload({
container: $("#panel")
});
} else {
- $(".flux .content img").lazyload();
+ $(".flux_content img").lazyload();
}
}
+}
- if (hide_posts) {
- $(".flux:not(.active) .flux_content").hide ();
- }
+function init_posts() {
+ //init_img(); //Alex
+ init_lazyload();
- var box_to_follow = $(window);
- var relative_follow = false;
+ var box_to_follow = $(window),
+ relative_follow = false;
if (is_global_mode()) {
box_to_follow = $("#panel");
relative_follow = true;
}
if (auto_mark_scroll) {
- box_to_follow.scroll(function() {
- $('.flux.not_read:visible').each(function() {
- if ($(this).children(".flux_content").is(':visible') &&
- inMarkViewport($(this), box_to_follow, relative_follow)) {
+ box_to_follow.scroll(function () {
+ $('.not_read:visible').each(function () {
+ if ($(this).children(".flux_content").is(':visible') && inMarkViewport($(this), box_to_follow, relative_follow)) {
mark_read($(this), true);
}
});
@@ -262,147 +250,142 @@ function init_posts () {
}
if (auto_load_more) {
- box_to_follow.scroll(function() {
+ 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();
- var load_more_top = load_more.position().top;
+ if (!load_more.is(':visible')) {
+ return;
+ }
+ var boxBot = box_to_follow.scrollTop() + box_to_follow.height(),
+ load_more_top = load_more.position().top;
if (relative_follow) {
load_more_top += box_to_follow.scrollTop();
}
if (boxBot >= load_more_top) {
- load_more_posts ();
+ load_more_posts();
}
});
}
}
-function init_column_categories () {
+function init_column_categories() {
if (!is_normal_mode()) {
return;
}
-
- //TODO: toggle class in PHP and remove the CSS changes done in JavaScript
- $(".category:not(.all):not(.favorites) .btn:first-child").width ("160px");
- $(".category:not(.all):not(.favorites)").addClass("stick").
- append ("<a class=\"btn dropdown-toggle\" href=\"#\"><i class=\"icon i_down\"></i></a>");
-
- $(".category + .feeds").not(".active").hide();
- $(".category.active a.dropdown-toggle i").toggleClass ("i_up");
-
- $(".category a.dropdown-toggle").click (function () {
- $(this).children ().toggleClass ("i_up");
- $(this).parent ().next (".feeds").slideToggle();
+ $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () {
+ $(this).children().toggleClass("i_down").toggleClass("i_up");
+ $(this).parent().next(".feeds").slideToggle();
return false;
});
}
-function init_shortcuts () {
+function init_shortcuts() {
// Touches de manipulation
- shortcut.add(shortcuts['mark_read'], function () {
+ shortcut.add(shortcuts.mark_read, function () {
// on marque comme lu ou non lu
- active = $(".flux.active");
- mark_read (active, false);
+ var active = $(".flux.active");
+ mark_read(active, false);
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
- shortcut.add("shift+"+shortcuts['mark_read'], function () {
+ shortcut.add("shift+" + shortcuts.mark_read, function () {
// on marque tout comme lu
- url = $(".nav_menu a.read_all").attr ("href");
- redirect (url, false);
+ var url = $(".nav_menu a.read_all").attr("href");
+ redirect(url, false);
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
- shortcut.add(shortcuts['mark_favorite'], function () {
+ shortcut.add(shortcuts.mark_favorite, function () {
// on marque comme favori ou non favori
- active = $(".flux.active");
- mark_favorite (active);
+ var active = $(".flux.active");
+ mark_favorite(active);
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
// Touches de navigation
- shortcut.add(shortcuts['prev_entry'], prev_entry, {
- 'disable_in_input':true
+ shortcut.add(shortcuts.prev_entry, prev_entry, {
+ 'disable_in_input': true
});
- shortcut.add("shift+"+shortcuts['prev_entry'], function () {
- old_active = $(".flux.active");
- first = $(".flux:first");
+ shortcut.add("shift+" + shortcuts.prev_entry, function () {
+ var old_active = $(".flux.active"),
+ first = $(".flux:first");
if (first.hasClass("flux")) {
- toggleContent (first, old_active);
+ toggleContent(first, old_active);
}
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
- shortcut.add(shortcuts['next_entry'], next_entry, {
- 'disable_in_input':true
+ shortcut.add(shortcuts.next_entry, next_entry, {
+ 'disable_in_input': true
});
- shortcut.add("shift+"+shortcuts['next_entry'], function () {
- old_active = $(".flux.active");
- last = $(".flux:last");
+ shortcut.add("shift+" + shortcuts.next_entry, function () {
+ var old_active = $(".flux.active"),
+ last = $(".flux:last");
if (last.hasClass("flux")) {
- toggleContent (last, old_active);
+ toggleContent(last, old_active);
}
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
- shortcut.add(shortcuts['go_website'], function () {
- url_website = $(".flux.active .link a").attr ("href");
+ shortcut.add(shortcuts.go_website, function () {
+ var url_website = $(".flux.active .link a").attr("href");
if (auto_mark_site) {
- $(".flux.active").each (function () {
+ $(".flux.active").each(function () {
mark_read($(this), true);
});
}
- redirect (url_website, true);
+ redirect(url_website, true);
}, {
- 'disable_in_input':true
+ 'disable_in_input': true
});
}
function init_stream_delegates(divStream) {
- divStream.on('click', '.flux_header .item.title, .flux_header .item.date', function (e) { //flux_header_toggle
- old_active = $(".flux.active");
- new_active = $(this).parent ().parent ();
+ divStream.on('click', '.flux_header>.item.title, .flux_header>.item.date', function (e) { //flux_header_toggle
+ var old_active = $(".flux.active"),
+ new_active = $(this).parent().parent();
if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone
if (auto_mark_article) {
mark_read(new_active, true);
}
return true;
}
- toggleContent (new_active, old_active);
+ toggleContent(new_active, old_active);
});
divStream.on('click', '.flux a.read', function () {
- active = $(this).parents (".flux");
- mark_read (active, false);
+ var active = $(this).parents(".flux");
+ mark_read(active, false);
return false;
});
divStream.on('click', '.flux a.bookmark', function () {
- active = $(this).parents (".flux");
- mark_favorite (active);
+ var active = $(this).parents(".flux");
+ mark_favorite(active);
return false;
});
divStream.on('click', '.flux .content a', function () {
- $(this).attr ('target', '_blank');
+ $(this).attr('target', '_blank');
});
- divStream.on('click', '.item.title>a',function (e) {
- if (e.ctrlKey) return true; //Allow default control-click behaviour such as open in backround-tab
- $(this).parent ().click (); //Will perform toggle flux_content
+ divStream.on('click', '.item.title>a', function (e) {
+ if (e.ctrlKey) {
+ return true; //Allow default control-click behaviour such as open in backround-tab
+ }
+ $(this).parent().click(); //Will perform toggle flux_content
return false;
});
- divStream.on('click', '.bigMarkAsRead', function() {
- url = $(".nav_menu a.read_all").attr ("href");
- redirect (url, false);
+ divStream.on('click', '.bigMarkAsRead', function () {
+ var url = $(".nav_menu .read_all").attr("href");
+ redirect(url, false);
return false;
});
@@ -414,30 +397,31 @@ function init_stream_delegates(divStream) {
}
function init_nav_entries() {
- $('.nav_entries a.previous_entry').click(function() {
+ var $nav_entries = $('#nav_entries');
+ $nav_entries.find('.previous_entry').click(function () {
prev_entry();
return false;
});
- $('.nav_entries a.next_entry').click(function() {
+ $nav_entries.find('.next_entry').click(function () {
next_entry();
return false;
});
- $('.nav_entries a.up').click(function() {
- var active_item = $(".flux.active");
- var windowTop = $(window).scrollTop();
- var item_top = active_item.position ().top;
+ $nav_entries.find('.up').click(function () {
+ var active_item = $(".flux.active"),
+ windowTop = $(window).scrollTop(),
+ item_top = active_item.position().top;
if (windowTop > item_top) {
- $("html,body").scrollTop (item_top);
+ $("html,body").scrollTop(item_top);
} else {
- $("html,body").scrollTop (0);
+ $("html,body").scrollTop(0);
}
return false;
});
}
function init_templates() {
- $('#aside_flux').on('click', '.dropdown-toggle', function () {
+ $('#aside_flux').on('click', '.feeds .dropdown-toggle', function () {
if ($(this).nextAll('.dropdown-menu').length === 0) {
var feed_id = $(this).closest('li').attr('id').substr(2),
feed_web = $(this).data('fweb'),
@@ -448,42 +432,83 @@ function init_templates() {
}
function init_actualize() {
- $("#actualize").click (function () {
- $.getScript('./?c=javascript&a=actualize').done(function() {
- updateFeeds ();
+ $("#actualize").click(function () {
+ $.getScript('./?c=javascript&a=actualize').done(function () {
+ updateFeeds();
});
return false;
});
}
-function closeNotification () {
- $(".notification").slideUp (200, function () {
- $(".notification").remove ();
+function closeNotification() {
+ $(".notification").slideUp(200, function () {
+ $(".notification").remove();
});
}
function init_notifications() {
- notif = $(".notification");
+ var notif = $(".notification");
if (notif[0] !== undefined) {
- timer = setInterval('closeNotification()', 5000);
+ window.setInterval(closeNotification, 4000);
- notif.find ("a.close").click (function () {
- closeNotification ();
+ notif.find("a.close").click(function () {
+ closeNotification();
return false;
});
}
}
-$(function () {
- if (is_reader_mode()) {
- hide_posts = false;
+//<endless_mode>
+var url_load_more = "",
+ load_more = false;
+
+function load_more_posts() {
+ if (load_more || url_load_more === '') {
+ return;
+ }
+
+ load_more = true;
+ $('#load_more').addClass('loading');
+ $.get(url_load_more, function (data) {
+ $stream.children('.flux:last').after($('#stream', data).children('.flux'));
+ $('.pagination').replaceWith($('.pagination', data));
+
+ init_load_more();
+ init_lazyload();
+
+ $('#load_more').removeClass('loading');
+ load_more = false;
+ });
+}
+
+function init_load_more() {
+ var $next_link = $("#load_more");
+ if (!$next_link.length) {
+ // no more article to load
+ url_load_more = "";
+ return;
}
- init_posts ();
- init_column_categories ();
- init_shortcuts ();
- init_stream_delegates($('#stream'));
- init_nav_entries();
- init_templates();
- init_notifications();
- init_actualize();
-});
+
+ url_load_more = $next_link.attr("href");
+
+ $next_link.click(function () {
+ load_more_posts();
+ return false;
+ });
+}
+//</endless_mode>
+
+if (document.addEventListener) { //jQuery not ready yet
+ document.addEventListener('DOMContentLoaded', function () {
+ $stream = $('#stream');
+ init_posts();
+ init_column_categories();
+ init_shortcuts();
+ init_stream_delegates($stream);
+ init_nav_entries();
+ init_templates();
+ init_notifications();
+ init_actualize();
+ init_load_more();
+ }, false);
+}