2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ===================================================================
8 * Unless otherwise specified, all software contained herein is licensed
9 * under the Apache License, Version 2.0 (the "License");
10 * you may not use this software except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * Unless otherwise specified, all documentation contained herein is licensed
22 * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23 * you may not use this documentation except in compliance with the License.
24 * You may obtain a copy of the License at
26 * https://creativecommons.org/licenses/by/4.0/
28 * Unless required by applicable law or agreed to in writing, documentation
29 * distributed under the License is distributed on an "AS IS" BASIS,
30 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 * See the License for the specific language governing permissions and
32 * limitations under the License.
34 * ============LICENSE_END============================================
41 angular.module('ecompApp').directive('imageUpload', function factory($q) {
42 var imageMimeRgx = /^image\/[a-zA-Z0-9]*$/;
44 var URL = window.URL || window.webkitURL;
46 var getResizeArea = function () {
47 var resizeAreaId = 'fileupload-resize-area';
49 var resizeArea = document.getElementById(resizeAreaId);
52 resizeArea = document.createElement('canvas');
53 resizeArea.id = resizeAreaId;
54 resizeArea.style.visibility = 'hidden';
55 document.body.appendChild(resizeArea);
61 var resizeImage = function (origImage, options) {
62 var maxHeight = options.resizeMaxHeight || 300;
63 var maxWidth = options.resizeMaxWidth || 250;
64 var quality = options.resizeQuality || 0.7;
65 var type = options.resizeType || 'image/jpg';
67 var canvas = getResizeArea();
69 var height = origImage.height;
70 var width = origImage.width;
72 //image redraw starting points
75 // calculate the width and height, constraining the proportions
77 if (width > maxWidth) {
78 height = Math.round(height *= maxWidth / width);
82 y0 = Math.round((maxHeight - height)/2);
90 if (height > maxHeight) {
91 width = Math.round(width *= maxHeight / height);
94 x0 = Math.round((maxWidth - width)/2);
104 canvas.width = maxWidth;
105 canvas.height = maxHeight;
107 //draw image on canvas
108 var ctx = canvas.getContext('2d');
110 //set background color
111 if(options.backgroundColor){
112 ctx.fillStyle = options.backgroundColor;
113 ctx.fillRect(0,0,maxWidth,maxHeight);
117 ctx.drawImage(origImage, x0, y0, width, height);
119 // get the data from canvas as 70% jpg (or specified type).
120 return canvas.toDataURL(type, quality);
123 var createImage = function(url, callback) {
124 var image = new Image();
125 image.onload = function() {
131 var fileToDataURL = function (file) {
132 var deferred = $q.defer();
133 var reader = new FileReader();
134 reader.onload = function (e) {
135 deferred.resolve(e.target.result);
137 reader.readAsDataURL(file);
138 return deferred.promise;
142 * Image Upload directive
143 * ************************
144 * image-upload: image object , Mandatory
145 * image-upload-resize-max-height: <Number>, Optional (default 300), resize maximum height
146 * image-upload-resize-max-width: <Number>, Optional (default 270), resize maximum width
147 * image-upload-resize-quality: <Number>, Optional, value can be 0.0-1.0 (default 0.7), resize compression quality
148 * image-upload-resize-type: <String>, Optional, (default 'image/jpg'), image mime type
149 * image-upload-api: <Object>, Optional, pass an api reference object and get api.clearFile() function - clear input field and reset form validation
150 * image-upload-background-color: <String> color name, Optional, background color fill if image doesn't fit the whole desired resize area.
152 * in addition, if <input> element is part of <form>, in order to get form validation please set its 'name' attribute and 'ng-model' to get the following field validation errors:
153 * - 'mimeType' : in case the uploaded image is not an image
154 * - 'imageSize' : in case the image size (in bytes) is too large
161 image: '=imageUpload',
162 resizeMaxHeight: '@?imageUploadResizeMaxHeight',
163 resizeMaxWidth: '@?imageUploadResizeMaxWidth',
164 resizeQuality: '@?imageUploadResizeQuality',
165 resizeType: '@?imageUploadResizeType',
166 imageApi: '=?imageUploadApi',
167 backgroundColor: '@?imageUploadBackgroundColor'
169 compile: function compile(tElement, tAttrs, transclude) {
170 return function postLink(scope, iElement, iAttrs, formCtrl) {
171 var doResizing = function(imageResult, callback) {
172 createImage(imageResult.url, function(image) {
173 var dataURL = resizeImage(image, scope);
174 imageResult.resized = {
176 type: dataURL.match(/:(.+\/.+);/)[1]
178 callback(imageResult);
182 var applyScope = function(imageResult) {
183 scope.$apply(function() {
184 //console.log(imageResult);
186 scope.image.push(imageResult);
188 scope.image = imageResult;
192 iElement.bind('change', function (evt) {
193 //when multiple always return an array of images
197 var files = evt.target.files;
198 for(var i = 0; i < files.length; i++) {
199 setInputValidity(files[i]);
201 //create a result object for each file in files
204 url: URL.createObjectURL(files[i])
207 fileToDataURL(files[i]).then(function (dataURL) {
208 imageResult.dataURL = dataURL;
211 if(scope.resizeMaxHeight || scope.resizeMaxWidth) { //resize image
212 doResizing(imageResult, function(imageResult) {
213 applyScope(imageResult);
217 applyScope(imageResult);
222 //API for otter actions
223 scope.imageApi = scope.imageApi || {};
224 scope.imageApi.clearFile = () => {
225 iElement[0].value = '';
230 let setInputValidity = file => {
231 //if form validation supported
233 if(formCtrl && iAttrs.name && formCtrl[iAttrs.name]){
234 formCtrl[iAttrs.name].$setDirty();
235 if(file && file.type && !imageMimeRgx.test(file.type)){
237 formCtrl[iAttrs.name].$setValidity('mimeType', false);
241 if(file && file.size && file.size > 1000000){
243 formCtrl[iAttrs.name].$setValidity('imageSize', false);
248 formCtrl[iAttrs.name].$setValidity('mimeType', true);
249 formCtrl[iAttrs.name].$setValidity('imageSize', true);