From d964f7efaa8b369f9acf8eaf73436bdea0865734 Mon Sep 17 00:00:00 2001 From: Daniel Herrero Date: Tue, 13 Feb 2018 13:15:03 +0100 Subject: [PATCH] SPR1.3 TASK#36 - zoom image --- client/core/src/core.js | 1 + client/core/src/directives/index.js | 1 + .../src/directives/specs/zoom-image.spec.js | 71 +++++++++++++++ client/core/src/directives/zoom-image.js | 89 +++++++++++++++++++ client/core/src/styles/zoom-image.css | 40 +++++++++ .../item/src/descriptor/item-descriptor.html | 4 +- 6 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 client/core/src/directives/specs/zoom-image.spec.js create mode 100644 client/core/src/directives/zoom-image.js create mode 100644 client/core/src/styles/zoom-image.css diff --git a/client/core/src/core.js b/client/core/src/core.js index 6bc5b8bdc..2889a690e 100644 --- a/client/core/src/core.js +++ b/client/core/src/core.js @@ -1,5 +1,6 @@ import './styles/mdl-override.css'; import './styles/mdi-override.css'; +import './styles/zoom-image.css'; export * from './module'; export * from './directives/index'; diff --git a/client/core/src/directives/index.js b/client/core/src/directives/index.js index da672b330..9a6531b1e 100644 --- a/client/core/src/directives/index.js +++ b/client/core/src/directives/index.js @@ -4,3 +4,4 @@ import './dialog'; import './validation'; import './acl'; import './on-error-src'; +import './zoom-image'; diff --git a/client/core/src/directives/specs/zoom-image.spec.js b/client/core/src/directives/specs/zoom-image.spec.js new file mode 100644 index 000000000..1ee7bbd79 --- /dev/null +++ b/client/core/src/directives/specs/zoom-image.spec.js @@ -0,0 +1,71 @@ +describe('Directive zoomImage', () => { + let idContainer = 'zoomImage'; + let compile; + let scope; + let srcDefault = 'http://default.img.jpg/'; + let srcZoom = 'http://zoom.img.jpg/'; + let findContainer; + + beforeEach(() => { + angular.mock.module('client'); + }); + + beforeEach(angular.mock.inject(($compile, $rootScope) => { + compile = $compile; + scope = $rootScope.$new(); + })); + + afterEach(() => { + findContainer = document.getElementById(idContainer); + if (findContainer) { + findContainer.parentNode.removeChild(findContainer); + findContainer = undefined; + } + }); + + function getCompiledImage(imgHtml) { + let element = angular.element(imgHtml); + var compiledElement = compile(element)(scope); + scope.$digest(); + return compiledElement; + } + + it('should create zoom container when click into image', () => { + let image = getCompiledImage(``); + image[0].click(); + findContainer = document.getElementById(idContainer); + + expect(findContainer).not.toBeNull(); + }); + + it('should detroy zoom container when click outside zoomed image', () => { + let image = getCompiledImage(``); + image[0].click(); + findContainer = document.getElementById(idContainer); + + let findOutsideImage = findContainer.querySelector('.zoomImage-background'); + findOutsideImage.click(); + + findContainer = document.getElementById(idContainer); + + expect(findContainer).toBeNull(); + }); + + it('should create new image, into zoom container, with src as original image src', () => { + let image = getCompiledImage(``); + image[0].click(); + findContainer = document.getElementById(idContainer); + let findNewImage = findContainer.querySelector('img'); + + expect(findNewImage.src).toEqual(srcDefault); + }); + + it('should create new image, into zoom container, with src likes zoomImage value', () => { + let image = getCompiledImage(``); + image[0].click(); + findContainer = document.getElementById(idContainer); + let findNewImage = findContainer.querySelector('img'); + + expect(findNewImage.src).toEqual(srcZoom); + }); +}); diff --git a/client/core/src/directives/zoom-image.js b/client/core/src/directives/zoom-image.js new file mode 100644 index 000000000..dc75eda40 --- /dev/null +++ b/client/core/src/directives/zoom-image.js @@ -0,0 +1,89 @@ +import ngModule from '../module'; + +export function directive($timeout) { + let idContainer = 'zoomImage'; + let container; + let background; + let image; + + function createContainers(src) { + if (document.getElementById(idContainer)) { + destroyContainers(); + } + container = document.createElement('div'); + container.id = idContainer; + + background = document.createElement('div'); + background.className = 'zoomImage-background'; + container.appendChild(background); + + image = document.createElement('img'); + image.src = src; + container.appendChild(image); + + document.body.appendChild(container); + + $timeout(() => { + resizeImage(); + container.className = 'open'; + }, 250); + } + + function addListeners() { + background.addEventListener('click', destroyContainers); + document.addEventListener('keydown', e => keyDownHandler(e)); + window.addEventListener('resize', resizeImage); + } + + function removeListeners() { + if (container) { + background.removeEventListener('click', destroyContainers); + document.removeEventListener('keydown', e => keyDownHandler(e)); + window.removeEventListener('resize', resizeImage); + } + } + + function keyDownHandler(event) { + if (event.keyCode === 27) { + destroyContainers(); + } + } + + function destroyContainers() { + if (document.getElementById(idContainer)) { + removeListeners(); + container.parentNode.removeChild(container); + } + + container = undefined; + background = undefined; + image = undefined; + } + + function resizeImage() { + if (image) { + image.style.marginLeft = `-${Math.floor(image.clientWidth / 2)}px`; + image.style.marginTop = `-${Math.floor(image.clientHeight / 2)}px`; + } + } + + return { + restrict: 'A', + priority: 9999, + link: function($scope, $element, $attrs) { + $element.on('click', function(event) { + let src = $attrs.zoomImage || $attrs.src; + if (src) { + createContainers(src); + addListeners(); + } else + throw new Error('No image source detected'); + + event.preventDefault(); + }); + } + }; +} +directive.$inject = ['$timeout']; + +ngModule.directive('zoomImage', directive); diff --git a/client/core/src/styles/zoom-image.css b/client/core/src/styles/zoom-image.css new file mode 100644 index 000000000..f21db8d13 --- /dev/null +++ b/client/core/src/styles/zoom-image.css @@ -0,0 +1,40 @@ +img[zoom-image]{ + cursor: zoom-in; +} + +div#zoomImage, div#zoomImage .zoomImage-background { + width: 100%; + height: 100%; + position: fixed; + top: 0; + z-index: 11; +} +div#zoomImage{ + opacity: 0; + transition: visibility 0s, opacity 0.5s linear; +} + +div#zoomImage .zoomImage-background{ + background: rgba(0, 0, 0, 0.7); + cursor: zoom-out; +} +div#zoomImage img{ + z-index: 12; + position: fixed; + max-height: 98%; + max-width: 98%; + left: 50%; + top: 50%; + opacity: 0; + transition: visibility 0s, opacity 1s linear; +} + +div#zoomImage.open { + visibility: visible; + opacity: 1; +} + +div#zoomImage.open img{ + visibility: visible; + opacity: 1; +} \ No newline at end of file diff --git a/client/item/src/descriptor/item-descriptor.html b/client/item/src/descriptor/item-descriptor.html index 286e0c733..3837e838a 100644 --- a/client/item/src/descriptor/item-descriptor.html +++ b/client/item/src/descriptor/item-descriptor.html @@ -4,7 +4,9 @@ - +
Id: {{$ctrl.item.id}}