├── .gitignore ├── package.json ├── bower.json ├── LICENSE ├── README.md └── ionic-image-lazy-load.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | .idea/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-image-lazy-load", 3 | "version": "1.0.0", 4 | "authors": [ 5 | "Vincius Zilli Pavei ", 6 | "Michel Vidailhet " 7 | ], 8 | "description": "Directive to Ionic Framework that only loads an image when it is seen by the user.", 9 | "main": "ionic-image-lazy-load.js", 10 | "scripts": {}, 11 | "license": "MIT", 12 | "dependencies": {}, 13 | "devDependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-image-lazy-load", 3 | "main": "ionic-image-lazy-load.js", 4 | "version": "1.0.0", 5 | "homepage": "https://github.com/paveisistemas/ionic-image-lazy-load", 6 | "authors": [ 7 | "Vincius Zilli Pavei ", 8 | "Michel Vidailhet " 9 | ], 10 | "description": "Directive to Ionic Framework that only loads an image when it is seen by the user.", 11 | "moduleType": [ 12 | "amd" 13 | ], 14 | "keywords": [ 15 | "ionic", 16 | "lazy", 17 | "load", 18 | "image" 19 | ], 20 | "license": "MIT", 21 | "ignore": [ 22 | "**/.*", 23 | "node_modules", 24 | "bower_components", 25 | "test", 26 | "tests" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Pavei Sistemas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ionic-image-lazy-load 2 | ===================== 3 | 4 | 5 | ## Demo 6 | http://codepen.io/mvidailhet/pen/yNOGzY 7 | http://codepen.io/pavei/pen/oFpCy 8 | 9 | ## Quick Start 10 | 11 | Install using bower 12 | 13 | ```sh 14 | bower install ion-image-lazy-load --save 15 | ``` 16 | 17 | or 18 | 19 | 20 | Download the file JS *ionic-image-lazy-load.js*, save on your project and load it on your *index.html*. 21 | 22 | 23 | ```html 24 | 25 | ``` 26 | 27 | Load into your module: 28 | 29 | ```javascript 30 | angular.module('yourapp', 31 | ['ionic', 'ionicLazyLoad']) 32 | ``` 33 | 34 | Set the `lazy-scroll` directive on your `` tag, that will listen to the scroll event: 35 | 36 | ``` javascript 37 | 38 | ``` 39 | 40 | And set the `image-lazy-src` directive on the image attribute instead of `src`: 41 | 42 | ```javascript 43 | 44 | ``` 45 | 46 | You can also use it as a background-image for an element by setting the `image-lazy-background-image` paramameter to true: 47 | ``` javascript 48 |
49 | ``` 50 | 51 | You can also set an option to auto call `$ionicScrollDelegate.resize()` when the image `load` (default value is `false`): 52 | 53 | ```javascript 54 | 55 | ``` 56 | 57 | To show a ionic spinner while the image is loading, just specify a ionic spinner type (list is here: http://ionicframework.com/docs/api/directive/ionSpinner/): 58 | 59 | ```javascript 60 | 61 | ``` 62 | Note: the styling of the loader position is up to you. The directive adds this html: 63 | 64 | ```html 65 |
66 | 67 |
68 | ``` 69 | 70 | You can set a distance from the bottom or right side of the screen where the image will start loading. 71 | This will allow to start loading the image 100px below the bottom of the screen: 72 | 73 | ``` javascript 74 | 75 | ``` 76 | 77 | This will allow to start loading the image 100px before the right side of the screen: 78 | ```javascript 79 | 80 | ``` 81 | -------------------------------------------------------------------------------- /ionic-image-lazy-load.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by PAVEI on 30/09/2014. 3 | * Updated by Ross Martin on 12/05/2014 4 | * Updated by Davide Pastore on 04/14/2015 5 | * Updated by Michel Vidailhet on 05/12/2015 6 | * Updated by Rene Korss on 11/25/2015 7 | */ 8 | 9 | angular.module('ionicLazyLoad', []); 10 | 11 | angular.module('ionicLazyLoad') 12 | 13 | .directive('lazyScroll', ['$rootScope', 14 | function($rootScope) { 15 | return { 16 | restrict: 'A', 17 | link: function ($scope, $element) { 18 | var origEvent = $scope.$onScroll; 19 | $scope.$onScroll = function () { 20 | $rootScope.$broadcast('lazyScrollEvent'); 21 | 22 | if(typeof origEvent === 'function'){ 23 | origEvent(); 24 | } 25 | }; 26 | } 27 | }; 28 | }]) 29 | 30 | .directive('imageLazySrc', ['$document', '$timeout', '$ionicScrollDelegate', '$compile', 31 | function ($document, $timeout, $ionicScrollDelegate, $compile) { 32 | return { 33 | restrict: 'A', 34 | scope: { 35 | lazyScrollResize: "@lazyScrollResize", 36 | imageLazyBackgroundImage: "@imageLazyBackgroundImage", 37 | imageLazySrc: "@" 38 | }, 39 | link: function ($scope, $element, $attributes) { 40 | if (!$attributes.imageLazyDistanceFromBottomToLoad) { 41 | $attributes.imageLazyDistanceFromBottomToLoad = 0; 42 | } 43 | if (!$attributes.imageLazyDistanceFromRightToLoad) { 44 | $attributes.imageLazyDistanceFromRightToLoad = 0; 45 | } 46 | 47 | var loader; 48 | if ($attributes.imageLazyLoader) { 49 | loader = $compile('
')($scope); 50 | $element.after(loader); 51 | } 52 | 53 | $scope.$watch('imageLazySrc', function (oldV, newV) { 54 | if(loader) 55 | loader.remove(); 56 | if ($attributes.imageLazyLoader) { 57 | loader = $compile('
')($scope); 58 | $element.after(loader); 59 | } 60 | var deregistration = $scope.$on('lazyScrollEvent', function () { 61 | // console.log('scroll'); 62 | if (isInView()) { 63 | loadImage(); 64 | deregistration(); 65 | } 66 | } 67 | ); 68 | $timeout(function () { 69 | if (isInView()) { 70 | loadImage(); 71 | deregistration(); 72 | } 73 | }, 500); 74 | }); 75 | var deregistration = $scope.$on('lazyScrollEvent', function () { 76 | // console.log('scroll'); 77 | if (isInView()) { 78 | loadImage(); 79 | deregistration(); 80 | } 81 | } 82 | ); 83 | 84 | function loadImage() { 85 | //Bind "load" event 86 | $element.bind("load", function (e) { 87 | if ($attributes.imageLazyLoader) { 88 | loader.remove(); 89 | } 90 | if ($scope.lazyScrollResize == "true") { 91 | //Call the resize to recalculate the size of the screen 92 | $ionicScrollDelegate.resize(); 93 | } 94 | $element.unbind("load"); 95 | }); 96 | 97 | if ($scope.imageLazyBackgroundImage == "true") { 98 | var bgImg = new Image(); 99 | bgImg.onload = function () { 100 | if ($attributes.imageLazyLoader) { 101 | loader.remove(); 102 | } 103 | $element[0].style.backgroundImage = 'url(' + $attributes.imageLazySrc + ')'; // set style attribute on element (it will load image) 104 | if ($scope.lazyScrollResize == "true") { 105 | //Call the resize to recalculate the size of the screen 106 | $ionicScrollDelegate.resize(); 107 | } 108 | }; 109 | bgImg.src = $attributes.imageLazySrc; 110 | } else { 111 | $element[0].src = $attributes.imageLazySrc; // set src attribute on element (it will load image) 112 | } 113 | } 114 | 115 | function isInView() { 116 | var clientHeight = $document[0].documentElement.clientHeight; 117 | var clientWidth = $document[0].documentElement.clientWidth; 118 | var imageRect = $element[0].getBoundingClientRect(); 119 | return (imageRect.top >= 0 && imageRect.top <= clientHeight + parseInt($attributes.imageLazyDistanceFromBottomToLoad)) 120 | && (imageRect.left >= 0 && imageRect.left <= clientWidth + parseInt($attributes.imageLazyDistanceFromRightToLoad)); 121 | } 122 | 123 | // bind listener 124 | // listenerRemover = scrollAndResizeListener.bindListener(isInView); 125 | 126 | // unbind event listeners if element was destroyed 127 | // it happens when you change view, etc 128 | $element.on('$destroy', function () { 129 | deregistration(); 130 | }); 131 | 132 | // explicitly call scroll listener (because, some images are in viewport already and we haven't scrolled yet) 133 | $timeout(function () { 134 | if (isInView()) { 135 | loadImage(); 136 | deregistration(); 137 | } 138 | }, 500); 139 | } 140 | }; 141 | }]); 142 | --------------------------------------------------------------------------------