diff --git a/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-image.jpg b/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-image.jpg new file mode 100644 index 0000000000..fd62385a83 Binary files /dev/null and b/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-image.jpg differ diff --git a/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-thumb.jpg b/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-thumb.jpg new file mode 100644 index 0000000000..ab33fb4a1c Binary files /dev/null and b/src/Umbraco.Web.UI.Client/src/assets/img/mocks/big-thumb.jpg differ diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js index fbe6a0456c..d8c45dca6d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js @@ -5,21 +5,20 @@ * @function **/ angular.module("umbraco.directives") - .directive('umbImageCrop', function ($timeout, localizationService, $log) { + .directive('umbImageCrop', + function ($timeout, localizationService, cropperHelper, $log) { return { restrict: 'E', replace: true, templateUrl: 'views/directives/imaging/umb-image-crop.html', scope: { src: '=', - width: '=', - height: '=', + width: '@', + height: '@', crop: "=" }, + link: function(scope, element, attrs) { - - scope.scale = 100; - //if image is over this, we re-calculate the editors global ratio //this will not have an effect on the result, since that is returned in percentage scope.maxHeight = 500; @@ -33,15 +32,19 @@ angular.module("umbraco.directives") cropper:{}, viewport:{}, margin: 20, - ratio: 1 + scale: { + min: 0.3, + max: 3, + current: 1 + } }; scope.style = function () { - return { - 'height': (parseInt(scope.height, 10) + 2 * scope.dimensions.margin) + 'px', - 'width': (parseInt(scope.width, 10) + 2 * scope.dimensions.margin) + 'px' - }; - }; + return { + 'height': (parseInt(scope.height, 10) + 2 * scope.dimensions.margin) + 'px', + 'width': (parseInt(scope.width, 10) + 2 * scope.dimensions.margin) + 'px' + }; + }; //elements @@ -52,10 +55,17 @@ angular.module("umbraco.directives") //default constraints for drag n drop var constraints = {left: {max: 20, min: 20}, top: {max: 20, min: 20}, }; - - var setDimensions = function(){ - scope.dimensions.image.width = $image.width(); - scope.dimensions.image.height = $image.height(); + var setDimensions = function(originalImage){ + originalImage.width("auto"); + originalImage.height("auto"); + + scope.dimensions.image.originalWidth = originalImage.width(); + scope.dimensions.image.originalHeight = originalImage.height(); + + scope.dimensions.image.width = originalImage.width(); + scope.dimensions.image.height = originalImage.height(); + scope.dimensions.image.left = originalImage[0].offsetLeft; + scope.dimensions.image.top = originalImage[0].offsetTop; scope.dimensions.viewport.width = $viewport.width(); scope.dimensions.viewport.height = $viewport.height(); @@ -67,36 +77,28 @@ angular.module("umbraco.directives") var setImageSize = function(width, height){ $image.width(width); $image.height(height); + scope.dimensions.image.width = width; scope.dimensions.image.height = height; + scope.dimensions.image.left = $image[0].offsetLeft; + scope.dimensions.image.top = $image[0].offsetTop; }; //when loading an image without any crop info, we center and fit it var fitImage = function(){ fitToViewPort($image); - centerImage($image); + + cropperHelper.centerInsideViewPort($image, $viewport); + syncOverLay(); setConstraints($image); }; - //utill for centering scaled image - var centerImage = function(img) { - var image_width = img.width(), - image_height = img.height(), - mask_width = $viewport.width(), - mask_height = $viewport.height(); - - img.css({ - 'position': 'absolute', - 'left': scope.dimensions.viewport.width / 2 - scope.dimensions.image.width / 2, - 'top': scope.dimensions.viewport.height / 2 - scope.dimensions.image.height / 2 - }); - }; - //utill for scaling image to fit viewport var fitToViewPort = function(img) { + //returns size fitting the cropper - var size = calculateAspectRatioFit( + var size = cropperHelper.calculateAspectRatioFit( scope.dimensions.image.width, scope.dimensions.image.height, scope.dimensions.cropper.width, @@ -106,20 +108,16 @@ angular.module("umbraco.directives") //sets the image size and updates the scope setImageSize(size.width, size.height); - scope.minScale = size.ratio; - scope.maxScale = size.ratio * 3; - scope.currentScale = scope.minScale; - scope.scale = scope.currentScale; + scope.dimensions.scale.min = size.ratio; + scope.dimensions.scale.max = size.ratio * 3; + scope.dimensions.scale.current = size.ratio; }; + var resizeImageToScale = function(img, ratio){ //do stuff - var size = calculateSizeToRatio(scope.dimensions.image.originalWidth, scope.dimensions.image.originalHeight, ratio); - + var size = cropperHelper.calculateSizeToRatio(scope.dimensions.image.originalWidth, scope.dimensions.image.originalHeight, ratio); setImageSize(size.width, size.height); - centerImage(img); - scope.currentScale = scope.scale; - syncOverLay(); }; @@ -135,23 +133,7 @@ angular.module("umbraco.directives") constraints.top.min = 20 + crop_height - h; }; - //utill for getting either min/max aspect ratio to scale image after - var calculateAspectRatioFit = function(srcWidth, srcHeight, maxWidth, maxHeight, maximize) { - var ratio = [maxWidth / srcWidth, maxHeight / srcHeight ]; - - if(maximize){ - ratio = Math.max(ratio[0], ratio[1]); - }else{ - ratio = Math.min(ratio[0], ratio[1]); - } - - return { width:srcWidth*ratio, height:srcHeight*ratio, ratio: ratio}; - }; - //utill for scaling width / height given a ratio - var calculateSizeToRatio= function(srcWidth, srcHeight, ratio) { - return { width:srcWidth*ratio, height:srcHeight*ratio, ratio: ratio}; - }; var calculateCropBox = function(){ scope.crop.left = Math.abs($image[0].offsetLeft - scope.dimensions.margin) / scope.dimensions.image.width; @@ -169,9 +151,20 @@ angular.module("umbraco.directives") var cropped_width = scope.dimensions.image.originalWidth - left; var ratio = cropped_width / scope.dimensions.image.originalWidth; - scope.scale = ratio; - resizeImageToScale($image, ratio); + var original = cropperHelper.calculateAspectRatioFit( + scope.dimensions.image.originalWidth, + scope.dimensions.image.originalHeight, + scope.dimensions.cropper.width, + scope.dimensions.cropper.height, + true); + scope.dimensions.scale.current = ratio; + + //min max based on original width/height + scope.dimensions.scale.min = original.ratio; + scope.dimensions.scale.max = 2; + + resizeImageToScale($image, ratio); $image.css({ "top": -top, "left": -left @@ -181,7 +174,6 @@ angular.module("umbraco.directives") }; - var syncOverLay = function(){ $overlay.height($image.height()); $overlay.width($image.width()); @@ -194,6 +186,8 @@ angular.module("umbraco.directives") calculateCropBox(); }; + + //Drag and drop positioning, using jquery ui draggable var onStartDragPosition, top, left; $overlay.draggable({ @@ -201,8 +195,6 @@ angular.module("umbraco.directives") syncOverLay(); }, drag: function(event, ui) { - - if(ui.position.left <= constraints.left.max && ui.position.left >= constraints.left.min){ $image.css({ 'left': ui.position.left @@ -215,50 +207,59 @@ angular.module("umbraco.directives") }); } }, - stop: function() { + stop: function(event, ui) { + + scope.dimensions.image.left = $image[0].offsetLeft; + scope.dimensions.image.top = $image[0].offsetTop; + + syncOverLay(); } }); + var init = function(image){ + scope.loaded = false; + + //set dimensions on image, viewport, cropper etc + setDimensions(image); + + //if we have a crop already position the image + if(scope.crop && scope.crop.top){ + calculatePosition(scope.crop); + }else{ + //if not, reset it and fit the image to the viewport + scope.crop = {}; + fitImage(); + } + + scope.loaded = true; + }; //// INIT ///// $image.load(function(){ $timeout(function(){ - $image.width("auto"); - $image.height("auto"); - - scope.dimensions.image.originalWidth = $image.width(); - scope.dimensions.image.originalHeight = $image.height(); - - setDimensions(); - - if(scope.crop && scope.crop.top){ - calculatePosition(scope.crop); - }else{ - scope.crop = {}; - fitImage(); - } - - scope.loaded = true; + init($image); }); }); /// WATCHERS //// - scope.$watch("scale", function(){ - if(scope.loaded && scope.scale !== scope.currentScale){ - resizeImageToScale($image, scope.scale); - setConstraints($image); - } + scope.$watchCollection('[width, height]', function(newValues, oldValues){ + //we have to reinit the whole thing if + //one of the external params changes + if(newValues !== oldValues){ + setDimensions($image); + } }); - /// WATCHERS //// - scope.$watch("crop", function(newVal, oldVal){ - if(scope.loaded && newVal !== oldVal){ - calculatePosition(scope.crop); + + scope.$watch("dimensions.scale.current", function(){ + if(scope.loaded){ + resizeImageToScale($image, scope.dimensions.scale.current); + setConstraints($image); } }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js index 03f3dd7b7e..c37e6fc319 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js @@ -20,98 +20,57 @@ angular.module("umbraco.directives") }, link: function(scope, element, attrs) { + scope.dimensions = { + width: 0, + height: 0, + left: 0, + top: 0 + }; + //elements var $viewport = element.find(".viewport"); var $image = element.find("img"); var $overlay = element.find(".overlay"); + scope.style = function () { + return { + 'top': scope.dimensions.top + 'px', + 'left': scope.dimensions.left + 'px' + }; + }; var setDimensions = function(){ - scope.imagewidth = $image.width(); - scope.imageheight = $image.height(); - }; + scope.dimensions.width = $image.width(); + scope.dimensions.height = $image.height(); - var setImageSize = function(width, height){ - $image.width(width); - $image.height(height); - - $viewport.width(width); - $viewport.height(height); - }; - - var fitImage = function(){ - fitToViewPort($image); - centerImage($image); - $log.log("centered and fitted"); - }; - - //utill for centering scaled image - var centerImage = function(img) { - img.css({ - 'position': 'absolute', - 'left': scope.width / 2 - scope.imageWidth / 2, - 'top': scope.height / 2 - scope.imageHeight / 2 - }); - }; - - //utill for scaling image to fit viewport - var fitToViewPort = function(img) { - //returns size fitting the cropper - var size = calculateAspectRatioFit( - scope.imageWidth, - scope.imageHeight, - scope.width, - scope.height, - false); - - //sets the image size and updates the scope - setImageSize(size.width, size.height); - }; - - - //utill for getting either min/max aspect ratio to scale image after - var calculateAspectRatioFit = function(srcWidth, srcHeight, maxWidth, maxHeight, maximize) { - var ratio = [maxWidth / srcWidth, maxHeight / srcHeight ]; - - if(maximize){ - ratio = Math.max(ratio[0], ratio[1]); - }else{ - ratio = Math.min(ratio[0], ratio[1]); + if(scope.gravity){ + scope.dimensions.left = scope.gravity.left * scope.dimensions.width -10; + scope.dimensions.top = scope.gravity.top * scope.dimensions.height -10; } - - return { width:srcWidth*ratio, height:srcHeight*ratio, ratio: ratio}; }; - + var calculateGravity = function(){ - scope.gravity.left = $overlay[0].offsetLeft + 10; - scope.gravity.top = $overlay[0].offsetTop + 10; + scope.dimensions.left = $overlay[0].offsetLeft + 10; + scope.dimensions.top = $overlay[0].offsetTop + 10; + + scope.gravity.left = scope.gravity.left / scope.dimensions.width; + scope.gravity.top = scope.gravity.top / scope.dimensions.height; }; //Drag and drop positioning, using jquery ui draggable - var onStartDragPosition, top, left; $overlay.draggable({ stop: function() { calculateGravity(); } }); - //// INIT ///// $image.load(function(){ - $timeout(function(){ - $image.width("auto"); - $image.height("auto"); - setDimensions(); - fitImage(); - - scope.loaded = true; }); }); - - } }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagethumbnail.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagethumbnail.directive.js index b3ff344224..e8c4afeda0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagethumbnail.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagethumbnail.directive.js @@ -7,7 +7,8 @@ * Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form. **/ angular.module("umbraco.directives") - .directive('umbImageThumbnail', function ($timeout, localizationService, $log) { + .directive('umbImageThumbnail', + function ($timeout, localizationService, cropperHelper, $log) { return { restrict: 'E', replace: true, diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/mediahelperService.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/mediahelperService.mocks.js index 61e80b60c9..78196212ac 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/mediahelperService.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/mediahelperService.mocks.js @@ -19,7 +19,7 @@ function mediaHelper(umbRequestHelper) { * @param {object} options.imageOnly Optional, if true then will only return a path if the media item is an image */ getMediaPropertyValue: function (options) { - return "assets/img/mocks/image.jpg"; + return "assets/img/mocks/big-image.jpg"; }, /** @@ -35,7 +35,7 @@ function mediaHelper(umbRequestHelper) { * @param {object} options.imageModel The media object to retrieve the image path from */ getImagePropertyValue: function (options) { - return "assets/img/mocks/image.jpg"; + return "assets/img/mocks/big-image.jpg"; }, /** * @ngdoc function diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.httpbackend.js b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.httpbackend.js index 2cd9545e6a..372fb69c95 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.httpbackend.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.httpbackend.js @@ -1,7 +1,7 @@ var umbracoAppDev = angular.module('umbraco.httpbackend', ['umbraco', 'ngMockE2E', 'umbraco.mocks']); -function initBackEnd($httpBackend, contentMocks, mediaMocks, treeMocks, userMocks, contentTypeMocks, sectionMocks, entityMocks, dataTypeMocks, dashboardMocks, macroMocks, utilMocks, localizationMocks, prevaluesMocks, imageHelperMocks) { +function initBackEnd($httpBackend, contentMocks, mediaMocks, treeMocks, userMocks, contentTypeMocks, sectionMocks, entityMocks, dataTypeMocks, dashboardMocks, macroMocks, utilMocks, localizationMocks, prevaluesMocks) { console.log("httpBackend inited"); @@ -18,8 +18,6 @@ function initBackEnd($httpBackend, contentMocks, mediaMocks, treeMocks, userMock utilMocks.register(); localizationMocks.register(); prevaluesMocks.register(); - - imageHelperMocks.register(); entityMocks.register(); $httpBackend.whenGET(/^views\//).passThrough(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js new file mode 100644 index 0000000000..f6d61d8dd0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js @@ -0,0 +1,62 @@ +/** +* @ngdoc service +* @name umbraco.services.mediaHelper +* @description A helper object used for dealing with media items +**/ +function cropperHelper(umbRequestHelper) { + var service = { + //utill for getting either min/max aspect ratio to scale image after + calculateAspectRatioFit : function(srcWidth, srcHeight, maxWidth, maxHeight, maximize) { + var ratio = [maxWidth / srcWidth, maxHeight / srcHeight ]; + + if(maximize){ + ratio = Math.max(ratio[0], ratio[1]); + }else{ + ratio = Math.min(ratio[0], ratio[1]); + } + + return { width:srcWidth*ratio, height:srcHeight*ratio, ratio: ratio}; + }, + + + //utill for scaling width / height given a ratio + calculateSizeToRatio : function(srcWidth, srcHeight, ratio) { + return { width:srcWidth*ratio, height:srcHeight*ratio, ratio: ratio}; + }, + + + centerInsideViewPort : function(img, viewport){ + var image_width = img.width(), + image_height = img.height(), + mask_width = viewport.width(), + mask_height = viewport.height(), + image_top = img[0].offsetTop, + image_left = $image[0].offsetLeft, + change = true; + + var left = mask_width / 2 - image_width / 2, + top = mask_height / 2 - image_height / 2; + + /*check for overflow + if(image_left > 20 || image_left < mask_width - image_width){ + left = mask_width / 2 - image_width / 2; + change = true; + }*/ + + if(change){ + img.css({ + 'position': 'absolute', + 'left': left, + 'top': top + }); + } + + } + + + }; + + return service; +} + +angular.module('umbraco.services').factory('cropperHelper', cropperHelper); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/init.js b/src/Umbraco.Web.UI.Client/src/init.js index 974cfe97ee..f31e81e5d3 100644 --- a/src/Umbraco.Web.UI.Client/src/init.js +++ b/src/Umbraco.Web.UI.Client/src/init.js @@ -1,6 +1,6 @@ /** Executed when the application starts, binds to events and set global state */ -app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', - function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies) { +app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache', + function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache) { //This sets the default jquery ajax headers to include our csrf token, we diff --git a/src/Umbraco.Web.UI.Client/src/loader.js b/src/Umbraco.Web.UI.Client/src/loader.js index ffb61665a5..54bf9e0413 100644 --- a/src/Umbraco.Web.UI.Client/src/loader.js +++ b/src/Umbraco.Web.UI.Client/src/loader.js @@ -4,13 +4,8 @@ yepnope({ 'lib/jquery/jquery-2.0.3.min.js', /* the jquery ui elements we need */ - /* NOTE: I've opted not to use the full lib, just the parts we need to save on DL*/ - 'lib/jquery/jquery.ui.core.min.js', - 'lib/jquery/jquery.ui.widget.min.js', - - 'lib/jquery/jquery.ui.mouse.min.js', - 'lib/jquery/jquery.ui.sortable.min.js', - + 'lib/jquery/jquery-ui-1.10.3.custom.min.js', + /* 1.1.5 */ 'lib/angular/1.1.5/angular.min.js', 'lib/angular/1.1.5/angular-cookies.min.js', diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html index 82f83d56d6..a81493ab77 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html @@ -8,25 +8,8 @@ - -
-		{{dimensions | json}}
-
- -
-		{{box | json}}
-
- - + ng-model="dimensions.scale.current" /> \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html index 198e8d3f98..7f06c27ab4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html @@ -1,12 +1,16 @@
-
- +
+ -
+
+ + {{gravity | json }} + + {{dimensions | json }}
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 7ecf0a4b9a..5a0cdc9fc9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -11,7 +11,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl //Data sample var __img = { //image to crop - src: "assets/img/mocks/image.jpg", + src: "assets/img/mocks/big-image.jpg", //global gravity, used if not crop is specified gravity: {left: 0.5, top: 0.4}, @@ -20,8 +20,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl thumbnail: { //crop dimensions - width: "30px", - height: "40px", + width: 100, + height: 100, //crops in percentages crop:{ "left": 0.31731772342645215, @@ -33,8 +33,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl banner: { - width: "200px", - height: "20px", + width: 340, + height: 90, crop:{ "left": 0.31731772342645215, "top": 0.17420325244997603, @@ -45,8 +45,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl highrise: { - width: "20px", - height: "200px" + width: 90, + height: 340 }, } }; @@ -81,7 +81,6 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.edit = function(image){ $scope.currentImage = image; - $scope.cropper.image = __img; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html index 9e31aadddb..b95b4a6258 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html @@ -1,35 +1,38 @@
-
- +
-
+
+ height="200" + width= "380" + src="cropper.image.src" + gravity="cropper.point.gravity" />