'use strict'; crop.directive('imgCrop', ['$timeout', 'cropHost', 'cropPubSub', function($timeout, CropHost, CropPubSub) { return { restrict: 'E', scope: { image: '=', resultImage: '=', changeOnFly: '=', areaType: '@', areaMinSize: '=', resultImageSize: '=', resultImageFormat: '@', resultImageQuality: '=', onChange: '&', onLoadBegin: '&', onLoadDone: '&', onLoadError: '&' }, template: '', controller: ['$scope', function($scope) { $scope.events = new CropPubSub(); }], link: function(scope, element/*, attrs*/) { // Init Events Manager var events = scope.events; // Init Crop Host var cropHost=new CropHost(element.find('canvas'), {}, events); // Store Result Image to check if it's changed var storedResultImage; var updateResultImage=function(scope) { var resultImage=cropHost.getResultImageDataURI(); if(storedResultImage!==resultImage) { storedResultImage=resultImage; if(angular.isDefined(scope.resultImage)) { scope.resultImage=resultImage; } scope.onChange({$dataURI: scope.resultImage}); } }; // Wrapper to safely exec functions within $apply on a running $digest cycle var fnSafeApply=function(fn) { return function(){ $timeout(function(){ scope.$apply(function(scope){ fn(scope); }); }); }; }; // Setup CropHost Event Handlers events .on('load-start', fnSafeApply(function(scope){ scope.onLoadBegin({}); })) .on('load-done', fnSafeApply(function(scope){ scope.onLoadDone({}); })) .on('load-error', fnSafeApply(function(scope){ scope.onLoadError({}); })) .on('area-move area-resize', fnSafeApply(function(scope){ if(!!scope.changeOnFly) { updateResultImage(scope); } })) .on('area-move-end area-resize-end image-updated', fnSafeApply(function(scope){ updateResultImage(scope); })); // Sync CropHost with Directive's options scope.$watch('image',function(){ cropHost.setNewImageSource(scope.image); }); scope.$watch('areaType',function(){ cropHost.setAreaType(scope.areaType); updateResultImage(scope); }); scope.$watch('areaMinSize',function(){ cropHost.setAreaMinSize(scope.areaMinSize); updateResultImage(scope); }); scope.$watch('resultImageSize',function(){ cropHost.setResultImageSize(scope.resultImageSize); updateResultImage(scope); }); scope.$watch('resultImageFormat',function(){ cropHost.setResultImageFormat(scope.resultImageFormat); updateResultImage(scope); }); scope.$watch('resultImageQuality',function(){ cropHost.setResultImageQuality(scope.resultImageQuality); updateResultImage(scope); }); // Update CropHost dimensions when the directive element is resized scope.$watch( function () { return [element[0].clientWidth, element[0].clientHeight]; }, function (value) { cropHost.setMaxDimensions(value[0],value[1]); updateResultImage(scope); }, true ); // Destroy CropHost Instance when the directive is destroying scope.$on('$destroy', function(){ cropHost.destroy(); }); } }; }]);