diff options
| author | 2013-11-03 19:22:59 +0100 | |
|---|---|---|
| committer | 2013-11-04 23:31:36 +0100 | |
| commit | 231516f5238b6023001bed548569077c61411a4e (patch) | |
| tree | 2265c174152f3bc7c0fbe49f5a776bc4ca5c3020 /public/scripts/main.js | |
| parent | b23d66ec360208cf1e1d8ee2fc3bebf25997d9fa (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.js | 495 |
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); +} |
