Lazy Loading Images With AngularJS

by maxhq

HTML

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
<!--
Please note that under "Fiddle Options" (left) the following is set:
  <body ng-app="Demo" ng-controller="AppController">

And the following ressources are loaded:
  http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
  http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js
-->
<h1>Lazy Loading Images With AngularJS</h1>

<p>
	You have {{ photos.size }} photos in your set.
	<a ng-click="rebuildSet()">Rebuild set</a>.
	<a ng-click="changeSource()">Change src</a>.
	<a ng-click="clearPhotos()">Clear</a>.
</p>

<a ng-show="isBoxVisible" ng-click="hideBox()" class="box">
	This is a big thing that may change,
	causing the DOCUMENT HEIGHT to change.
</a>

<ul class="photos">
	<li ng-repeat="photo in photos" class="photo">
		<img bn-lazy-src="{{ photo.src }}" width="150" height="150" alt="Christina Cox"	/>
	</li>
</ul>

CSS

/* Add "click" styles because newer releases of AngularJS don't seem to add the HREF value. */
a[ ng-click ] {
	cursor: pointer ;
	text-decoration: underline ;
}

a.box {
	background-color: #FAFAFA ;
	border: 1px solid #CCCCCC ;
	display: block ;
	height: 200px ;
	line-height: 200px ;
	text-align: center ;
	width: 684px ;
}

ul.photos {
	list-style-type: none ;
	margin: 16px 0px 16px 0px ;
	padding: 0px 0px 0px 0px ;
	width: 700px ;
}

ul.photos:after {
	content: "" ;
	clear: both ;
	display: block ;
	height: 0px ;
}

li.photo {
	background-color: #FAFAFA ;
	border: 1px solid #CCCCCC ;
	border-radius: 4px 4px 4px 4px ;
	float: left ;
	margin: 0px 10px 10px 0px ;
	padding: 5px 5px 5px 5px ;
}

li.photo img {
	border: 1px solid #EEEEEE ;
	border-radius: 3px 3px 3px 3px ;
	display: block ;
}

img[ bn-lazy-src ] {
	background-image: url( "./checkered.png" ) ;
}

JavaScript

/* 
 * All credits go to Ben Nadel
 * (http://www.bennadel.com/blog/2498-Lazy-Loading-Image-With-AngularJS.htm)
 * I only put his code to JSfiddle and shortened it a bit (wiped out empty lines etc.)
 */

// Create an application module for our demo.
var app = angular.module( "Demo", [] );

// I control the root of the application.
app.controller("AppController", function( $scope ) {
	// I flag the visibility of the big box.
	$scope.isBoxVisible = true;

	// Build up a large set of images, all with unique
	// SRC values so that the browser cannot cache them.
	$scope.photos = buildPhotoSet( 200 );

	// ---
	// PUBLIC METHODS.
	// ---

	// change SRC values of existing photo set to examine how changes
	// to source will affect rendered / non-rendered images
	$scope.changeSource = function() {
		var now = ( new Date() ).getTime();
		// Update all SRC attribute to point to "1.jpg".
		for ( var i = 0 ; i < $scope.photos.length ; i++ ) {
			var photo = $scope.photos[ i ];
			photo.src = photo.src.replace( /\d\./i, "1." );
		}
	};

	// clear current photo set.
	$scope.clearPhotos = function() {
		$scope.photos = [];
	};

    // hide big box: this changes document dimensions (and possibly shows more images)
	$scope.hideBox = function() {
		$scope.isBoxVisible = false;
	};

	// rebuild entire photo set.
	$scope.rebuildSet = function() {
		$scope.photos = buildPhotoSet( 20 );
	};

	// ---
	// PRIVATE METHODS.
	// ---

	// return a photo set of the given size. Each photo will have a unique SRC value
	function buildPhotoSet( size ) {
		var photos = [];
		var now = ( new Date() ).getTime();

		for ( var i = 0 ; i < size ; i++ ) {
			var index = ( ( i % 3 ) + 1 );
			var version = ( now + i );
			photos.push({
				id: ( i + 1 ),
				src: ( "christina-cox-" + index + ".jpg?v=" + version )
			});
		}
		return( photos );
	}
});

// -------------------------------------------------- //
// -------------------------------------------------- //

// I lazily load the images, when they...