Rahul Desai
Rahul Desai

Reputation: 15501

unable to show AJAX loader while image is being loaded completely

I am working on a image slider and here is my code so far:

angular
.module('myApp', [])
.controller("imageController", ['$scope', function ($scope) {

  var imageArray = [  // dynamic array
    'http://s3.amazonaws.com/theoatmeal-img/thumbnails/random_comics.png',
    'http://images5.fanpop.com/image/photos/30200000/-random-30240825-200-200.gif',
    'https://cdn.tutsplus.com/active/uploads/legacy/tuts/059_QTRandom/Preview/Preview.png'
  ];

  var index = 0;  // so as to have the first image displayed when the page is loaded

  $scope.showAjaxLoader = true;  // show

  $scope.url = imageArray[index];

  $scope.showAjaxLoader = false;  // hide

  if(imageArray.length > 0){
    $scope.showNext = true;
  }

  $scope.getPrev = function(){
    $scope.showAjaxLoader = true;  // show
    
    index--;
    $scope.url = imageArray[index];
    if(index === 0){
      $scope.showPrev = false;
    }
    $scope.showNext = true;
    
    $scope.showAjaxLoader = false;  // hide
  };

  $scope.getNext = function(){
    $scope.showAjaxLoader = true;  // show
    
    index++;
    $scope.url = imageArray[index];
    if(index === imageArray.length-1){
      $scope.showNext = false;
    }
    $scope.showPrev = true;
    
    $scope.showAjaxLoader = false;  // hide
  };
}]);
img{
    width: 100%;
}

button{
    position: fixed;
    top: calc(50% - 17px);
    font-size: 25px;
}

#previous{
    left: 0px;
}

#next{
    right: 0px;
}

/* AJAX loader */

#circularG{
	position:relative;
	width:58px;
	height:58px;
	margin: auto;
}

.circularG{
	position:absolute;
	background-color:rgb(0,0,0);
	width:14px;
	height:14px;
	border-radius:9px;
		-o-border-radius:9px;
		-ms-border-radius:9px;
		-webkit-border-radius:9px;
		-moz-border-radius:9px;
	animation-name:bounce_circularG;
		-o-animation-name:bounce_circularG;
		-ms-animation-name:bounce_circularG;
		-webkit-animation-name:bounce_circularG;
		-moz-animation-name:bounce_circularG;
	animation-duration:1.1s;
		-o-animation-duration:1.1s;
		-ms-animation-duration:1.1s;
		-webkit-animation-duration:1.1s;
		-moz-animation-duration:1.1s;
	animation-iteration-count:infinite;
		-o-animation-iteration-count:infinite;
		-ms-animation-iteration-count:infinite;
		-webkit-animation-iteration-count:infinite;
		-moz-animation-iteration-count:infinite;
	animation-direction:normal;
		-o-animation-direction:normal;
		-ms-animation-direction:normal;
		-webkit-animation-direction:normal;
		-moz-animation-direction:normal;
}

#circularG_1{
	left:0;
	top:23px;
	animation-delay:0.41s;
		-o-animation-delay:0.41s;
		-ms-animation-delay:0.41s;
		-webkit-animation-delay:0.41s;
		-moz-animation-delay:0.41s;
}

#circularG_2{
	left:6px;
	top:6px;
	animation-delay:0.55s;
		-o-animation-delay:0.55s;
		-ms-animation-delay:0.55s;
		-webkit-animation-delay:0.55s;
		-moz-animation-delay:0.55s;
}

#circularG_3{
	top:0;
	left:23px;
	animation-delay:0.69s;
		-o-animation-delay:0.69s;
		-ms-animation-delay:0.69s;
		-webkit-animation-delay:0.69s;
		-moz-animation-delay:0.69s;
}

#circularG_4{
	right:6px;
	top:6px;
	animation-delay:0.83s;
		-o-animation-delay:0.83s;
		-ms-animation-delay:0.83s;
		-webkit-animation-delay:0.83s;
		-moz-animation-delay:0.83s;
}

#circularG_5{
	right:0;
	top:23px;
	animation-delay:0.97s;
		-o-animation-delay:0.97s;
		-ms-animation-delay:0.97s;
		-webkit-animation-delay:0.97s;
		-moz-animation-delay:0.97s;
}

#circularG_6{
	right:6px;
	bottom:6px;
	animation-delay:1.1s;
		-o-animation-delay:1.1s;
		-ms-animation-delay:1.1s;
		-webkit-animation-delay:1.1s;
		-moz-animation-delay:1.1s;
}

#circularG_7{
	left:23px;
	bottom:0;
	animation-delay:1.24s;
		-o-animation-delay:1.24s;
		-ms-animation-delay:1.24s;
		-webkit-animation-delay:1.24s;
		-moz-animation-delay:1.24s;
}

#circularG_8{
	left:6px;
	bottom:6px;
	animation-delay:1.38s;
		-o-animation-delay:1.38s;
		-ms-animation-delay:1.38s;
		-webkit-animation-delay:1.38s;
		-moz-animation-delay:1.38s;
}



@keyframes bounce_circularG{
	0%{
		transform:scale(1);
	}

	100%{
		transform:scale(.3);
	}
}

@-o-keyframes bounce_circularG{
	0%{
		-o-transform:scale(1);
	}

	100%{
		-o-transform:scale(.3);
	}
}

@-ms-keyframes bounce_circularG{
	0%{
		-ms-transform:scale(1);
	}

	100%{
		-ms-transform:scale(.3);
	}
}

@-webkit-keyframes bounce_circularG{
	0%{
		-webkit-transform:scale(1);
	}

	100%{
		-webkit-transform:scale(.3);
	}
}

@-moz-keyframes bounce_circularG{
	0%{
		-moz-transform:scale(1);
	}

	100%{
		-moz-transform:scale(.3);
	}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="imageController">

    <!-- AJAX loader -->
    <div id="circularG" ng-show='showAjaxLoader'>
      <div id="circularG_1" class="circularG"></div>
      <div id="circularG_2" class="circularG"></div>
      <div id="circularG_3" class="circularG"></div>
      <div id="circularG_4" class="circularG"></div>
      <div id="circularG_5" class="circularG"></div>
      <div id="circularG_6" class="circularG"></div>
      <div id="circularG_7" class="circularG"></div>
      <div id="circularG_8" class="circularG"></div>
    </div>

    <!-- Next/Previous buttons -->
    <button id='previous' ng-click='getPrev()' ng-init='showPrev=false' ng-show='showPrev'>Prev</button>
    <button id='next' ng-click='getNext()' ng-show='showNext'>Next</button>

    <!-- image -->
    <img src={{url}} />

  </div>
</body>

It works fine, except the fact that the AJAX loader is not displayed while the other image is being loaded completely. The problem is that it gets hidden immediately when I set the ng-show to false.

How do I make it to work so that it is shown while the image is being fetched or completely loaded on the webpage?

Upvotes: 1

Views: 98

Answers (2)

Ori Drori
Ori Drori

Reputation: 191976

Whenever an image url changes, a new javascript image object is created, and the image onload event is used to cancel the ajax loader.

Note that after an image was loaded, it is cached by the browser, so the ajax loader will usually appear once for every image. To see the ajax loader again, you'll have to clean the cache.

angular
.module('myApp', [])
.controller("imageController", ['$scope', function ($scope) {

  var imageArray = [  // dynamic array
    'http://s3.amazonaws.com/theoatmeal-img/thumbnails/random_comics.png',
    'http://images5.fanpop.com/image/photos/30200000/-random-30240825-200-200.gif',
    'https://cdn.tutsplus.com/active/uploads/legacy/tuts/059_QTRandom/Preview/Preview.png'
  ];

  var index = 0; // so as to have the first image displayed when the page is loaded

  showImage(imageArray[index]);

  function showImage(url) {
    $scope.showAjaxLoader = true; // show

    var img = new Image(); // create a new image

    img.onload = function () { // create an image onload event handler
      $scope.$apply(function () { // don't forget to apply as the event is out of angular digest cycle
        $scope.showAjaxLoader = false; // hide when image is loaded
      });

    };
    $scope.url = url;
    img.src = url; // assign url to image

  }

  if (imageArray.length > 0) {
    $scope.showNext = true;
  }

  $scope.getPrev = function () {
    index--;
    showImage(imageArray[index]);
    if (index === 0) {
      $scope.showPrev = false;
    }
    $scope.showNext = true;
  };

  $scope.getNext = function () {
    index++;
    showImage(imageArray[index]);
    if (index === imageArray.length - 1) {
      $scope.showNext = false;
    }
    $scope.showPrev = true;

  };
}
                               ]);
img{
  width: 100%;
}

button{
  position: fixed;
  top: calc(50% - 17px);
  font-size: 25px;
}

#previous{
  left: 0px;
}

#next{
  right: 0px;
}

/* AJAX loader */

#circularG{
  position: fixed;
  width:58px;
  height:58px;
  margin: auto;
  top: 100px;
  left: calc(50% - 29px);
}

.circularG{
  position:absolute;
  background-color:rgb(0,0,0);
  width:14px;
  height:14px;
  border-radius:9px;
  -o-border-radius:9px;
  -ms-border-radius:9px;
  -webkit-border-radius:9px;
  -moz-border-radius:9px;
  animation-name:bounce_circularG;
  -o-animation-name:bounce_circularG;
  -ms-animation-name:bounce_circularG;
  -webkit-animation-name:bounce_circularG;
  -moz-animation-name:bounce_circularG;
  animation-duration:1.1s;
  -o-animation-duration:1.1s;
  -ms-animation-duration:1.1s;
  -webkit-animation-duration:1.1s;
  -moz-animation-duration:1.1s;
  animation-iteration-count:infinite;
  -o-animation-iteration-count:infinite;
  -ms-animation-iteration-count:infinite;
  -webkit-animation-iteration-count:infinite;
  -moz-animation-iteration-count:infinite;
  animation-direction:normal;
  -o-animation-direction:normal;
  -ms-animation-direction:normal;
  -webkit-animation-direction:normal;
  -moz-animation-direction:normal;
}

#circularG_1{
  left:0;
  top:23px;
  animation-delay:0.41s;
  -o-animation-delay:0.41s;
  -ms-animation-delay:0.41s;
  -webkit-animation-delay:0.41s;
  -moz-animation-delay:0.41s;
}

#circularG_2{
  left:6px;
  top:6px;
  animation-delay:0.55s;
  -o-animation-delay:0.55s;
  -ms-animation-delay:0.55s;
  -webkit-animation-delay:0.55s;
  -moz-animation-delay:0.55s;
}

#circularG_3{
  top:0;
  left:23px;
  animation-delay:0.69s;
  -o-animation-delay:0.69s;
  -ms-animation-delay:0.69s;
  -webkit-animation-delay:0.69s;
  -moz-animation-delay:0.69s;
}

#circularG_4{
  right:6px;
  top:6px;
  animation-delay:0.83s;
  -o-animation-delay:0.83s;
  -ms-animation-delay:0.83s;
  -webkit-animation-delay:0.83s;
  -moz-animation-delay:0.83s;
}

#circularG_5{
  right:0;
  top:23px;
  animation-delay:0.97s;
  -o-animation-delay:0.97s;
  -ms-animation-delay:0.97s;
  -webkit-animation-delay:0.97s;
  -moz-animation-delay:0.97s;
}

#circularG_6{
  right:6px;
  bottom:6px;
  animation-delay:1.1s;
  -o-animation-delay:1.1s;
  -ms-animation-delay:1.1s;
  -webkit-animation-delay:1.1s;
  -moz-animation-delay:1.1s;
}

#circularG_7{
  left:23px;
  bottom:0;
  animation-delay:1.24s;
  -o-animation-delay:1.24s;
  -ms-animation-delay:1.24s;
  -webkit-animation-delay:1.24s;
  -moz-animation-delay:1.24s;
}

#circularG_8{
  left:6px;
  bottom:6px;
  animation-delay:1.38s;
  -o-animation-delay:1.38s;
  -ms-animation-delay:1.38s;
  -webkit-animation-delay:1.38s;
  -moz-animation-delay:1.38s;
}



@keyframes bounce_circularG{
  0%{
    transform:scale(1);
  }

  100%{
    transform:scale(.3);
  }
}

@-o-keyframes bounce_circularG{
  0%{
    -o-transform:scale(1);
  }

  100%{
    -o-transform:scale(.3);
  }
}

@-ms-keyframes bounce_circularG{
  0%{
    -ms-transform:scale(1);
  }

  100%{
    -ms-transform:scale(.3);
  }
}

@-webkit-keyframes bounce_circularG{
  0%{
    -webkit-transform:scale(1);
  }

  100%{
    -webkit-transform:scale(.3);
  }
}

@-moz-keyframes bounce_circularG{
  0%{
    -moz-transform:scale(1);
  }

  100%{
    -moz-transform:scale(.3);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="imageController">

    <!-- AJAX loader -->
    <div id="circularG" ng-show='showAjaxLoader'>
      <div id="circularG_1" class="circularG"></div>
      <div id="circularG_2" class="circularG"></div>
      <div id="circularG_3" class="circularG"></div>
      <div id="circularG_4" class="circularG"></div>
      <div id="circularG_5" class="circularG"></div>
      <div id="circularG_6" class="circularG"></div>
      <div id="circularG_7" class="circularG"></div>
      <div id="circularG_8" class="circularG"></div>
    </div>

    <!-- Next/Previous buttons -->
    <button id='previous' ng-click='getPrev()' ng-init='showPrev=false' ng-show='showPrev'>Prev</button>
    <button id='next' ng-click='getNext()' ng-show='showNext'>Next</button>

    <!-- image -->
    <img src={{url}} />

  </div>
</body>

Upvotes: 1

SaiGiridhar
SaiGiridhar

Reputation: 886

Here, is the alternate way using angular directive.

https://jsfiddle.net/8drLy2bp/1/

Directive:

angular
    .module('myApp', [])
    .directive('orientable', function () {       
    return {
        scope: false,
        link: function($scope, element, attrs) {   
           $scope.$watch("url", function(newValue){
            element.bind("load" , function(e){ 

                $scope.$apply(function(){
                   $scope.showAjaxLoader = false;
                });
            });
          });
        }
    }
    });

Upvotes: 0

Related Questions