angular img with loading spinner
by ffabreti
HTML
<p> open Chrome Dev-Tools and set to mobile device with slow network (ex: Regular 3G) </p>
<div ng-controller="c">
<img-with-loading
img-src="{{src}}"
spinner-class="{{spinnerClass}}">
</img-with-loading>
</div>
CSS
.background-spinner {
background-repeat: no-repeat;
background-position: center center;
background-image: url('https://www.yugma.com/images/loading-animation-7.gif')
}
JavaScript
var app = angular.module('app', []);
app.directive('imgWithLoading', function () {
return {
restrict: 'E',
template: '<div/>',
transclude: false,
replace: true,
scope: {
imgSrc: '@'
},
link: function (scope, element, attrs) {
console.log('imgWithLoading init: ' + scope.imgSrc);
var img = angular.element(new Image());
var unbind1 = img.on('load', function (evt) {
console.log('image loaded: ' + img.attr('src'));
stopLoadingCSS( );
});
var unbind2 = img.on('error', function(evt) {
console.log('imgWithLoading error Loading ' + scope.imgSrc);
element.removeClass(attrs.spinnerClass);
});
//only define src here, after binding events
//notice src is retrieve from attrs because scope.imgSrc may be undefined yet
img.attr('src', attrs.imgSrc);
startLoadingCSS( );
element.append(img);
//watch for changes
var unbind3 = scope.$watch('imgSrc', function(newVal, oldVal) {
if ( newVal===img.attr('src') ) return;
startLoadingCSS( );
img.attr('src', newVal);
console.log('imgWithLoading: imgSrc mudou: ' + newVal );
console.log('imgWithLoading: imgSrc antigo: ' + oldVal );
});
scope.$on('destroy', function() {
console.log('imgWithLoading: unbinding...');
unbind1(); unbind2(); unbind3(); });
// ------- LOCAL FUNCTIONS --------------------------------
function startLoadingCSS( ) {
img.css({visibility: 'hidden'});
element.addClass(attrs.spinnerClass);
}
function stopLoadingCSS( ) {
img.css({visibility: 'visible'});
...