diff --git a/src/components/images/imageFetcher.js b/src/components/images/imageFetcher.js index 1e13cebc77..c7deadc1bd 100644 --- a/src/components/images/imageFetcher.js +++ b/src/components/images/imageFetcher.js @@ -2,28 +2,36 @@ define(['dom'], function (dom) { 'use strict'; function loadImage(elem, url) { - if (!elem) { return Promise.reject('elem cannot be null'); } if (elem.tagName !== "IMG") { - elem.style.backgroundImage = "url('" + url + "')"; return Promise.resolve(); - - //return loadImageIntoImg(document.createElement('img'), url).then(function () { - // elem.style.backgroundImage = "url('" + url + "')"; - // return Promise.resolve(); - //}); - } return loadImageIntoImg(elem, url); } + function unloadImage(elem) { + if (!elem) { + return Promise.reject('elem cannot be null'); + } + + var url; + if (elem.tagName !== "IMG") { + url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, ""); + elem.style.backgroundImage = 'none'; + } else { + url = elem.getAttribute("src"); + elem.setAttribute("src", ""); + } + + return Promise.resolve(url); + } + function loadImageIntoImg(elem, url) { return new Promise(function (resolve, reject) { - dom.addEventListener(elem, 'load', resolve, { once: true }); @@ -32,7 +40,8 @@ define(['dom'], function (dom) { } return { - loadImage: loadImage + loadImage: loadImage, + unloadImage: unloadImage }; }); diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index 28b6923c33..8e2bcedf82 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -3,40 +3,36 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', var self = {}; - function fillImage(elem, source, enableEffects) { - - if (!elem) { - throw new Error('elem cannot be null'); + function fillImage(entry) { + if (!entry) { + throw new Error('entry cannot be null'); } - if (!source) { - source = elem.getAttribute('data-src'); - } + var source = entry.target.getAttribute('data-src'); - if (!source) { - return; + if (entry.intersectionRatio > 0 && source) { + fillImageElement(entry.target, source); + } else if (!source) { + emptyImageElement(entry.target); } - - fillImageElement(elem, source, enableEffects); } - function fillImageElement(elem, source, enableEffects) { + function fillImageElement(elem, source) { imageFetcher.loadImage(elem, source).then(function () { - - if (enableEffects !== false) { - fadeIn(elem); + if (userSettings.enableFastFadein()) { + elem.classList.add('lazy-image-fadein-fast'); + } else { + elem.classList.add('lazy-image-fadein'); } elem.removeAttribute("data-src"); }); } - function fadeIn(elem) { - if (userSettings.enableFastFadein()) { - elem.classList.add('lazy-image-fadein-fast'); - } else { - elem.classList.add('lazy-image-fadein'); - } + function emptyImageElement(elem) { + imageFetcher.unloadImage(elem).then(function (url) { + elem.setAttribute("data-src", url); + }); } function lazyChildren(elem) { diff --git a/src/components/lazyloader/lazyloader-intersectionobserver.js b/src/components/lazyloader/lazyloader-intersectionobserver.js index 5f83742601..377e3d0cff 100644 --- a/src/components/lazyloader/lazyloader-intersectionobserver.js +++ b/src/components/lazyloader/lazyloader-intersectionobserver.js @@ -11,42 +11,15 @@ define(['require', 'browser'], function (require, browser) { } LazyLoader.prototype.createObserver = function () { + var callback = this.options.callback; - var observerOptions = {}; - var options = this.options; - var loadedCount = 0; - var callback = options.callback; - - observerOptions.rootMargin = "50%"; - - var observerId = 'obs' + new Date().getTime(); - - var self = this; - var observer = new IntersectionObserver(function (entries) { - for (var j = 0, length2 = entries.length; j < length2; j++) { - var entry = entries[j]; - - if (entry.intersectionRatio > 0) { - - // Stop watching and load the image - var target = entry.target; - - observer.unobserve(target); - - if (!target[observerId]) { - target[observerId] = 1; - callback(target); - loadedCount++; - - if (loadedCount >= self.elementCount) { - self.destroyObserver(); - } - } - } - } - }, - observerOptions - ); + var observer = new IntersectionObserver( + (entries, observer) => { + entries.forEach(entry => { + callback(entry); + }, + {rootMargin: "50%"}); + }); this.observer = observer; }; diff --git a/src/components/lazyloader/lazyloader-scroll.js b/src/components/lazyloader/lazyloader-scroll.js deleted file mode 100644 index 4930f6376c..0000000000 --- a/src/components/lazyloader/lazyloader-scroll.js +++ /dev/null @@ -1,185 +0,0 @@ -define(['visibleinviewport', 'dom', 'browser'], function (visibleinviewport, dom, browser) { - 'use strict'; - - var thresholdX; - var thresholdY; - - function resetThresholds() { - - var threshold = 0.3; - - thresholdX = screen.availWidth * threshold; - thresholdY = screen.availHeight * threshold; - } - - function resetThresholdsOnTimer() { - - setTimeout(resetThresholds, 500); - } - - if (browser.iOS) { - dom.addEventListener(window, "orientationchange", resetThresholdsOnTimer, { passive: true }); - dom.addEventListener(window, 'resize', resetThresholdsOnTimer, { passive: true }); - } else { - dom.addEventListener(window, "orientationchange", resetThresholds, { passive: true }); - dom.addEventListener(window, 'resize', resetThresholds, { passive: true }); - } - resetThresholds(); - - function isVisible(elem) { - return visibleinviewport(elem, true, thresholdX, thresholdY); - } - - var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel'); - var self = {}; - - function cancelAll(tokens) { - for (var i = 0, length = tokens.length; i < length; i++) { - - tokens[i] = true; - } - } - - function unveilElementsInternal(instance, callback) { - - var unveiledElements = []; - var cancellationTokens = []; - var loadedCount = 0; - - function unveilInternal(tokenIndex) { - - var anyFound = false; - var out = false; - - var elements = instance.elements; - // TODO: This out construct assumes left to right, top to bottom - - for (var i = 0, length = elements.length; i < length; i++) { - - if (cancellationTokens[tokenIndex]) { - return; - } - if (unveiledElements[i]) { - continue; - } - var elem = elements[i]; - if (!out && isVisible(elem)) { - anyFound = true; - unveiledElements[i] = true; - callback(elem); - loadedCount++; - } else { - - if (anyFound) { - out = true; - } - } - } - - if (loadedCount >= elements.length) { - dom.removeEventListener(document, 'focus', unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(document, 'scroll', unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(document, wheelEvent, unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(window, 'resize', unveil, { - capture: true, - passive: true - }); - } - } - - function unveil() { - - cancelAll(cancellationTokens); - - var index = cancellationTokens.length; - cancellationTokens.length++; - - setTimeout(function () { - unveilInternal(index); - }, 1); - } - - dom.addEventListener(document, 'focus', unveil, { - capture: true, - passive: true - }); - dom.addEventListener(document, 'scroll', unveil, { - capture: true, - passive: true - }); - dom.addEventListener(document, wheelEvent, unveil, { - capture: true, - passive: true - }); - dom.addEventListener(window, 'resize', unveil, { - capture: true, - passive: true - }); - - unveil(); - } - - function LazyLoader(options) { - - this.options = options; - } - - LazyLoader.prototype.createObserver = function () { - - unveilElementsInternal(this, this.options.callback); - this.observer = 1; - }; - - LazyLoader.prototype.addElements = function (elements) { - - this.elements = this.elements || []; - - for (var i = 0, length = elements.length; i < length; i++) { - this.elements.push(elements[i]); - } - - var observer = this.observer; - - if (!observer) { - this.createObserver(); - } - - }; - - LazyLoader.prototype.destroyObserver = function (elements) { - - }; - - LazyLoader.prototype.destroy = function (elements) { - - this.destroyObserver(); - this.options = null; - }; - - function unveilElements(elements, root, callback) { - - if (!elements.length) { - return; - } - var lazyLoader = new LazyLoader({ - callback: callback - }); - lazyLoader.addElements(elements); - } - - LazyLoader.lazyChildren = function (elem, callback) { - - unveilElements(elem.getElementsByClassName('lazy'), elem, callback); - }; - - return LazyLoader; -}); diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index bb395f337c..f2c472dace 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -50,7 +50,8 @@ define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader return enableScrollX() ? "overflowPortrait" : "portrait"; } - function fillItemsContainer(elem) { + function fillItemsContainer(entry) { + var elem = entry.target; var id = elem.getAttribute("data-id"); var viewStyle = self.getCurrentViewStyle(); var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index 9a0823a6b9..aa46fd4361 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -50,7 +50,8 @@ define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader return enableScrollX() ? "overflowPortrait" : "portrait"; } - function fillItemsContainer(elem) { + function fillItemsContainer(entry) { + var elem = entry.target; var id = elem.getAttribute("data-id"); var viewStyle = self.getCurrentViewStyle(); var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; diff --git a/src/scripts/site.js b/src/scripts/site.js index 90fa1d849f..8957481242 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -379,12 +379,7 @@ var AppInfo = {}; define("filesystem", [componentsPath + "/filesystem"], returnFirstDependency); - if (window.IntersectionObserver && !browser.edge) { - define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); - } else { - define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency); - } - + define("lazyLoader", [componentsPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency); define("shell", [componentsPath + "/shell"], returnFirstDependency); define("apiclient", [bowerPath + "/apiclient/apiclient"], returnFirstDependency);