{"version":3,"file":"angular-lazy-image.dccacc43.js","mappings":"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","sources":["webpack://advanced-web/./node_modules/angular-lazy-image/release/lazy-image.js"],"sourcesContent":["/* global angular */\nangular.module('afkl.lazyImage', []);\n/* global angular */\nangular.module('afkl.lazyImage')\n .service('afklSrcSetService', ['$window', function($window) {\n 'use strict';\n\n /**\n * For other applications wanting the srccset/best image approach it is possible to use this module only\n * Loosely based on https://raw.github.com/borismus/srcset-polyfill/master/js/srcset-info.js\n */\n var INT_REGEXP = /^[0-9]+$/;\n\n // SRCSET IMG OBJECT\n function ImageInfo(options) {\n this.src = options.src;\n this.w = options.w || Infinity;\n this.h = options.h || Infinity;\n this.x = options.x || 1;\n }\n\n /**\n * Parse srcset rules\n * @param {string} descString Containing all srcset rules\n * @return {object} Srcset rules\n */\n var _parseDescriptors = function (descString) {\n\n var descriptors = descString.split(/\\s/);\n var out = {};\n\n for (var i = 0, l = descriptors.length; i < l; i++) {\n\n var desc = descriptors[i];\n\n if (desc.length > 0) {\n\n var lastChar = desc.slice(-1);\n var value = desc.substring(0, desc.length - 1);\n var intVal = parseInt(value, 10);\n var floatVal = parseFloat(value);\n\n if (value.match(INT_REGEXP) && lastChar === 'w') {\n out[lastChar] = intVal;\n } else if (value.match(INT_REGEXP) && lastChar === 'h') {\n out[lastChar] = intVal;\n } else if (!isNaN(floatVal) && lastChar === 'x') {\n out[lastChar] = floatVal;\n }\n\n }\n }\n\n return out;\n\n };\n\n /**\n * Returns best candidate under given circumstances\n * @param {object} images Candidate image\n * @param {function} criteriaFn Rule\n * @return {object} Returns best candidate under given criteria\n */\n var _getBestCandidateIf = function (images, criteriaFn) {\n\n var bestCandidate = images[0];\n\n for (var i = 0, l = images.length; i < l; i++) {\n var candidate = images[i];\n if (criteriaFn(candidate, bestCandidate)) {\n bestCandidate = candidate;\n }\n }\n\n return bestCandidate;\n\n };\n\n /**\n * Remove candidate under given circumstances\n * @param {object} images Candidate image\n * @param {function} criteriaFn Rule\n * @return {object} Removes images from global image collection (candidates)\n */\n var _removeCandidatesIf = function (images, criteriaFn) {\n\n for (var i = images.length - 1; i >= 0; i--) {\n var candidate = images[i];\n if (criteriaFn(candidate)) {\n images.splice(i, 1); // remove it\n }\n }\n\n return images;\n\n };\n\n /**\n * Direct implementation of \"processing the image candidates\":\n * http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#processing-the-image-candidates\n *\n * @param {array} imageCandidates (required)\n * @param {object} view (optional)\n * @returns {ImageInfo} The best image of the possible candidates.\n */\n var getBestImage = function (imageCandidates, view) {\n\n if (!imageCandidates) { return; }\n if (!view) {\n view = {\n 'w' : $window.innerWidth || document.documentElement.clientWidth,\n 'h' : $window.innerHeight || document.documentElement.clientHeight,\n 'x' : $window.devicePixelRatio || 1\n };\n }\n\n var images = imageCandidates.slice(0);\n\n /* LARGEST */\n // Width\n var largestWidth = _getBestCandidateIf(images, function (a, b) { return a.w > b.w; });\n // Less than client width.\n _removeCandidatesIf(images, (function () { return function (a) { return a.w < view.w; }; })(this));\n // If none are left, keep the one with largest width.\n if (images.length === 0) { images = [largestWidth]; }\n\n\n // Height\n var largestHeight = _getBestCandidateIf(images, function (a, b) { return a.h > b.h; });\n // Less than client height.\n _removeCandidatesIf(images, (function () { return function (a) { return a.h < view.h; }; })(this));\n // If none are left, keep one with largest height.\n if (images.length === 0) { images = [largestHeight]; }\n\n // Pixel density.\n var largestPxDensity = _getBestCandidateIf(images, function (a, b) { return a.x > b.x; });\n // Remove all candidates with pxdensity less than client pxdensity.\n _removeCandidatesIf(images, (function () { return function (a) { return a.x < view.x; }; })(this));\n // If none are left, keep one with largest pixel density.\n if (images.length === 0) { images = [largestPxDensity]; }\n\n\n /* SMALLEST */\n // Width\n var smallestWidth = _getBestCandidateIf(images, function (a, b) { return a.w < b.w; });\n // Remove all candidates with width greater than it.\n _removeCandidatesIf(images, function (a) { return a.w > smallestWidth.w; });\n\n // Height\n var smallestHeight = _getBestCandidateIf(images, function (a, b) { return a.h < b.h; });\n // Remove all candidates with height greater than it.\n _removeCandidatesIf(images, function (a) { return a.h > smallestHeight.h; });\n\n // Pixel density\n var smallestPxDensity = _getBestCandidateIf(images, function (a, b) { return a.x < b.x; });\n // Remove all candidates with pixel density less than smallest px density.\n _removeCandidatesIf(images, function (a) { return a.x > smallestPxDensity.x; });\n\n return images[0];\n\n };\n\n\n\n // options {src: null/string, srcset: string}\n // options.src normal url or null\n // options.srcset 997-s.jpg 480w, 997-m.jpg 768w, 997-xl.jpg 1x\n var getSrcset = function (options) {\n\n var imageCandidates = [];\n\n var srcValue = options.src;\n var srcsetValue = options.srcset;\n\n if (!srcsetValue) { return; }\n\n /* PUSH CANDIDATE [{src: _, x: _, w: _, h:_}, ...] */\n var _addCandidate = function (img) {\n\n for (var j = 0, ln = imageCandidates.length; j < ln; j++) {\n var existingCandidate = imageCandidates[j];\n\n // DUPLICATE\n if (existingCandidate.x === img.x &&\n existingCandidate.w === img.w &&\n existingCandidate.h === img.h) { return; }\n }\n\n imageCandidates.push(img);\n\n };\n\n\n var _parse = function () {\n\n var input = srcsetValue,\n position = 0,\n rawCandidates = [],\n url,\n descriptors;\n\n while (input !== '') {\n\n while (input.charAt(0) === ' ') {\n input = input.slice(1);\n }\n\n position = input.indexOf(' ');\n\n if (position !== -1) {\n\n url = input.slice(0, position);\n\n // if (url === '') { break; }\n\n input = input.slice(position + 1);\n\n position = input.indexOf(',');\n\n if (position === -1) {\n descriptors = input;\n input = '';\n } else {\n descriptors = input.slice(0, position);\n input = input.slice(position + 1);\n }\n\n rawCandidates.push({\n url: url,\n descriptors: descriptors\n });\n\n } else {\n\n rawCandidates.push({\n url: input,\n descriptors: ''\n });\n input = '';\n }\n\n }\n\n // FROM RAW CANDIDATES PUSH IMAGES TO COMPLETE SET\n for (var i = 0, l = rawCandidates.length; i < l; i++) {\n\n var candidate = rawCandidates[i],\n desc = _parseDescriptors(candidate.descriptors);\n\n _addCandidate(new ImageInfo({\n src: candidate.url,\n x: desc.x,\n w: desc.w,\n h: desc.h\n }));\n\n }\n\n if (srcValue) {\n _addCandidate(new ImageInfo({src: srcValue}));\n }\n\n };\n\n _parse();\n\n\n // Return best available image for current view based on our list of candidates\n var bestImage = getBestImage(imageCandidates);\n\n /**\n * Object returning best match at moment, and total collection of candidates (so 'image' API can be used by consumer)\n * @type {Object}\n */\n var object = {\n 'best': bestImage, // IMAGE INFORMATION WHICH FITS BEST WHEN API IS REQUESTED\n 'candidates': imageCandidates // ALL IMAGE CANDIDATES BY GIVEN SRCSET ATTRIBUTES\n };\n\n // empty collection\n imageCandidates = null;\n\n // pass best match and candidates\n return object;\n\n };\n\n // throttle function to be used in directive\n function throttle(callback, delay) {\n var last, deferTimer;\n return function() {\n var now = +new Date();\n if (last && now < last + delay) {\n clearTimeout(deferTimer);\n deferTimer = setTimeout(function () {\n last = now;\n callback();\n }, delay + last - now);\n } else {\n last = now;\n callback();\n }\n };\n }\n\n /**\n * PUBLIC API\n */\n return {\n get: getSrcset, // RETURNS BEST IMAGE AND IMAGE CANDIDATES\n image: getBestImage, // RETURNS BEST IMAGE WITH GIVEN CANDIDATES\n throttle: throttle // RETURNS A THROTTLER FUNCTION\n };\n\n\n }]);\n\n/* global angular */\nangular.module('afkl.lazyImage')\n .directive('afklImageContainer', function () {\n 'use strict';\n\n return {\n restrict: 'A',\n // We have to use controller instead of link here so that it will always run earlier than nested afklLazyImage directives\n controller: ['$scope', '$element', function ($scope, $element) {\n $element.data('afklImageContainer', $element);\n }]\n };\n })\n .directive('afklLazyImage', ['$rootScope', '$window', '$timeout', 'afklSrcSetService', '$parse', function ($rootScope, $window, $timeout, srcSetService, $parse) {\n 'use strict';\n\n // Use srcSetService to find out our best available image\n var bestImage = function (images) {\n var image = srcSetService.get({srcset: images});\n var sourceUrl;\n if (image) {\n sourceUrl = image.best.src;\n }\n return sourceUrl;\n };\n\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n\n var _concatImgAttrs = function (imgAttrs) {\n\n var result = [];\n var CLASSNAME = 'afkl-lazy-image';\n var setClass = false;\n\n if (!!options.imgAttrs) {\n result = Array.prototype.map.call(imgAttrs, function(item) {\n for (var key in item) {\n if (item.hasOwnProperty(key)) {\n\n // TODO: TITLE CAN COME LATER (FROM DATA MODEL)\n var value = item[key];\n if (key === 'class') {\n setClass = true;\n value = value + ' ' + CLASSNAME;\n }\n return String.prototype.concat.call(key, '=\"', value, '\"');\n }\n }\n });\n }\n\n if (!setClass) {\n result.push('class=\"' + CLASSNAME + '\"');\n }\n\n return result.join(' ');\n };\n\n // CONFIGURATION VARS\n var $container = element.inheritedData('afklImageContainer');\n if (!$container) {\n $container = angular.element(attrs.afklLazyImageContainer || $window);\n }\n\n var loaded = false;\n var timeout;\n\n var images = attrs.afklLazyImage; // srcset attributes\n var options = attrs.afklLazyImageOptions ? $parse(attrs.afklLazyImageOptions)(scope) : {}; // options (background, offset)\n\n var img = null; // Angular element to image which will be placed\n var currentImage = null; // current image url\n var offset = options.offset ? options.offset : 50; // default offset\n var imgAttrs = _concatImgAttrs(options.imgAttrs); // all image attributes like class, title, onerror\n\n var LOADING = 'afkl-lazy-image-loading';\n\n attrs.afklLazyImageLoaded = false;\n\n var _containerScrollTop = function () {\n // See if we can use jQuery, with extra check\n // TODO: check if number is returned\n if ($container.scrollTop) {\n var scrollTopPosition = $container.scrollTop();\n if (scrollTopPosition) {\n return scrollTopPosition;\n }\n }\n\n var c = $container[0];\n if (c.pageYOffset !== undefined) {\n return c.pageYOffset;\n }\n else if (c.scrollTop !== undefined) {\n return c.scrollTop;\n }\n\n return document.documentElement.scrollTop || 0;\n };\n\n var _containerInnerHeight = function () {\n if ($container.innerHeight) {\n return $container.innerHeight();\n }\n\n var c = $container[0];\n if (c.innerHeight !== undefined) {\n return c.innerHeight;\n } else if (c.clientHeight !== undefined) {\n return c.clientHeight;\n }\n\n return document.documentElement.clientHeight || 0;\n };\n\n // Begin with offset and update on resize\n var _elementOffset = function () {\n if (element.offset) {\n return element.offset().top;\n }\n var box = element[0].getBoundingClientRect();\n return box.top + _containerScrollTop() - document.documentElement.clientTop;\n };\n\n\n var _elementOffsetContainer = function () {\n if (element.offset) {\n return element.offset().top - $container.offset().top;\n }\n return element[0].getBoundingClientRect().top - $container[0].getBoundingClientRect().top;\n };\n\n // Update url of our image\n var _setImage = function () {\n if (options.background) {\n element[0].style.backgroundImage = 'url(\"' + currentImage +'\")';\n } else if (!!img) {\n img[0].src = currentImage;\n }\n };\n\n // Append image to DOM\n var _placeImage = function () {\n\n loaded = true;\n // What is my best image available\n var hasImage = bestImage(images);\n\n if (hasImage) {\n // we have to make an image if background is false (default)\n if (!options.background) {\n\n if (!img) {\n element.addClass(LOADING);\n img = angular.element('');\n img.one('load', _loaded);\n img.one('error', _error);\n // remove loading class when image is acually loaded\n element.append(img);\n }\n\n }\n\n // set correct src/url\n _checkIfNewImage();\n }\n\n // Element is added to dom, no need to listen to scroll anymore\n $container.off('scroll', _onViewChange);\n\n };\n\n // Check on resize if actually a new image is best fit, if so then apply it\n var _checkIfNewImage = function () {\n if (loaded) {\n var newImage = bestImage(images);\n \n if (newImage !== currentImage) {\n // update current url\n currentImage = newImage;\n\n // TODO: loading state...\n\n // update image url\n _setImage();\n }\n }\n };\n\n // First update our begin offset\n _checkIfNewImage();\n\n var _loaded = function () {\n\n attrs.$set('afklLazyImageLoaded', 'done');\n\n element.removeClass(LOADING);\n\n };\n\n var _error = function () {\n\n attrs.$set('afklLazyImageLoaded', 'fail');\n\n };\n\n // Check if the container is in view for the first time. Utilized by the scroll and resize events.\n var _onViewChange = function () {\n // only do stuff when not set already\n if (!loaded) {\n\n // Config vars\n var remaining, shouldLoad, windowBottom;\n\n var height = _containerInnerHeight();\n var scroll = _containerScrollTop();\n\n var elOffset = $container[0] === $window ? _elementOffset() : _elementOffsetContainer();\n windowBottom = $container[0] === $window ? height + scroll : height;\n\n remaining = elOffset - windowBottom;\n\n // Is our top of our image container in bottom of our viewport?\n //console.log($container[0].className, _elementOffset(), _elementPosition(), height, scroll, remaining, elOffset);\n shouldLoad = remaining <= offset;\n\n\n // Append image first time when it comes into our view, after that only resizing can have influence\n if (shouldLoad) {\n\n _placeImage();\n\n }\n\n }\n\n };\n\n var _onViewChangeThrottled = srcSetService.throttle(_onViewChange, 300);\n\n // EVENT: RESIZE THROTTLED\n var _onResize = function () {\n $timeout.cancel(timeout);\n timeout = $timeout(function() {\n _checkIfNewImage();\n _onViewChange();\n }, 300);\n };\n\n\n // Remove events for total destroy\n var _eventsOff = function() {\n\n $timeout.cancel(timeout);\n\n angular.element($window).off('resize', _onResize);\n angular.element($window).off('scroll', _onViewChangeThrottled);\n\n if ($container[0] !== $window) {\n $container.off('resize', _onResize);\n $container.off('scroll', _onViewChangeThrottled);\n }\n\n // remove image being placed\n if (img) {\n img.remove();\n }\n\n img = timeout = currentImage = undefined;\n };\n\n // set events for scrolling and resizing on window\n // even if container is not window it is important\n // to cover two cases:\n // - when container size is bigger than window's size\n // - when container's side is out of initial window border\n angular.element($window).on('resize', _onResize);\n angular.element($window).on('scroll', _onViewChangeThrottled);\n\n // if container is not window, set events for container as well\n if ($container[0] !== $window) {\n $container.on('resize', _onResize);\n $container.on('scroll', _onViewChangeThrottled);\n }\n\n // events for image change\n attrs.$observe('afklLazyImage', function () {\n images = attrs.afklLazyImage;\n if (loaded) {\n _placeImage();\n }\n });\n\n // Image should be directly placed\n if (options.nolazy) {\n _placeImage();\n }\n\n\n scope.$on('afkl.lazyImage.destroyed', _onResize);\n\n // Remove all events when destroy takes place\n scope.$on('$destroy', function () {\n // tell our other kids, i got removed\n $rootScope.$broadcast('afkl.lazyImage.destroyed');\n // remove our events and image\n return _eventsOff();\n });\n\n return _onViewChange();\n\n }\n };\n\n}]);\n"],"names":["angular","module","service","$window","INT_REGEXP","ImageInfo","options","this","src","w","Infinity","h","x","_parseDescriptors","descString","descriptors","split","out","i","l","length","desc","lastChar","slice","value","substring","intVal","parseInt","floatVal","parseFloat","match","isNaN","_getBestCandidateIf","images","criteriaFn","bestCandidate","candidate","_removeCandidatesIf","splice","getBestImage","imageCandidates","view","innerWidth","document","documentElement","clientWidth","innerHeight","clientHeight","devicePixelRatio","largestWidth","a","b","largestHeight","largestPxDensity","smallestWidth","smallestHeight","smallestPxDensity","get","srcValue","srcsetValue","srcset","_addCandidate","img","j","ln","existingCandidate","push","url","input","position","rawCandidates","charAt","indexOf","_parse","object","image","throttle","callback","delay","last","deferTimer","now","Date","clearTimeout","setTimeout","directive","restrict","controller","$scope","$element","data","$rootScope","$timeout","srcSetService","$parse","bestImage","sourceUrl","best","link","scope","element","attrs","$container","inheritedData","afklLazyImageContainer","timeout","loaded","afklLazyImage","afklLazyImageOptions","currentImage","offset","imgAttrs","result","CLASSNAME","setClass","Array","prototype","map","call","item","key","hasOwnProperty","String","concat","join","_concatImgAttrs","LOADING","afklLazyImageLoaded","_containerScrollTop","scrollTop","scrollTopPosition","c","undefined","pageYOffset","_placeImage","background","addClass","one","_loaded","_error","append","_checkIfNewImage","off","_onViewChange","newImage","style","backgroundImage","$set","removeClass","height","_containerInnerHeight","scroll","top","getBoundingClientRect","clientTop","_onViewChangeThrottled","_onResize","cancel","on","$observe","nolazy","$on","$broadcast","remove"],"sourceRoot":""}