bbc / Imager.js

Responsive images while we wait for srcset to finish cooking
Apache License 2.0
3.84k stars 224 forks source link

Added a cleanup method to Imager prototype #129

Open fiznool opened 8 years ago

fiznool commented 8 years ago

This provides a cleanup method for anybody using Imager in a SPA environment.

imager.cleanup()

The method removes any attached event listeners and ensures that the scroll debounce interval is cleared.

If this is acceptable I can look at adding documentation, etc if required.

thom4parisot commented 8 years ago

Hey :-) thanks for this contribution!

What is the expected step after a cleanup? Deleting the imager instance of reusing it for other purposes?

Eventually if you could share a snippet of imager in the context of your SPA it would be helpful to determine what are the responsibilities of this method.

Thanks!

fiznool commented 8 years ago

@oncletom Here's a snippet using Angular:

// imager.directive.js
angular
  .module('imager-test')
  .directive('imager', function($window, $timeout, $sce) {
    return {
      restrict: 'E',
      template:
      '<div class="delayed-image-load" data-src="{{:: src }}" data-alt="{{:: data.alt}}"></div>',
      replace: true,
      scope: {
        data: '=imagerData'
      },
      link: function(scope, element) {
        var Imager = $window.Imager;
        if(!Imager) {
          throw new Error('Imager.js must be loaded to use the <imager> directive.');
        }

        // Build the `src` variable from the imager data passed in
        scope.src = $sce.trustAsResourceUrl([
          scope.data.baseUrl,
          '/',
          scope.data.name,
          '-{width}{pixel_ratio}.',
          scope.data.extension
        ].join(''));

        $timeout(function() {
          // Give DOM time to repaint.
          var imager = new Imager(element, {
            availableWidths: scope.data.availableWidths,
            availablePixelRatios: scope.data.availablePixelRatios,
            onResize: true,
            lazyload: false
          });

          // Clean up our imager when the directive is removed from the DOM
          scope.$on('$destroy', function() {
            imager.cleanup();
          });
        });
      }
    };
  });
// app.controller.js
angular
  .module('imager-test')
  .controller('AppCtrl', function($scope) {
    $scope.imagerData = {
      baseUrl: 'http://example.com/path/to/images',
      name: 'logo',
      extension: 'png',
      alt: 'Logo',
      availableWidths: [200, 250, 300],
      availablePixelRatios: [1, 1.5, 2]
    };
  });
<div ng-controller="AppCtrl">
  <imager imager-data="imagerData"></imager>
</div>

So, the idea is, if the HTML snippet above is ever removed from the DOM, the scope.$on('$destroy') listener is fired, which cleans up the global events registered via the imager instance.

thom4parisot commented 8 years ago

Oh OK I get it. Which means you have one instance of Imager per image?

fiznool commented 8 years ago

Yes, that's right. I found it easier this way, in case different images have different availableWidths, availablePixelRatios, etc.

fiznool commented 8 years ago

@oncletom I finally got round to adding some tests for this PR. Hopefully this is enough to be considered for a merge?

The Travis tests seem to be failing due to not having the credentials for BrowserStack, but when running npm test locally everything passes.

fiznool commented 8 years ago

Bump... would love to see this merged.