github.com/apremalal/vamps-core@v1.0.1-0.20161221121535-d430b56ec174/server/webapps/app/base/plugins/jquery-file-upload/js/jquery.fileupload-angular.js (about) 1 /* 2 * jQuery File Upload AngularJS Plugin 2.2.0 3 * https://github.com/blueimp/jQuery-File-Upload 4 * 5 * Copyright 2013, Sebastian Tschan 6 * https://blueimp.net 7 * 8 * Licensed under the MIT license: 9 * http://www.opensource.org/licenses/MIT 10 */ 11 12 /* jshint nomen:false */ 13 /* global define, angular */ 14 15 (function (factory) { 16 'use strict'; 17 if (typeof define === 'function' && define.amd) { 18 // Register as an anonymous AMD module: 19 define([ 20 'jquery', 21 'angular', 22 './jquery.fileupload-image.js', 23 './jquery.fileupload-audio', 24 './jquery.fileupload-video', 25 './jquery.fileupload-validate' 26 ], factory); 27 } else { 28 factory(); 29 } 30 }(function () { 31 'use strict'; 32 33 angular.module('blueimp.fileupload', []) 34 35 // The fileUpload service provides configuration options 36 // for the fileUpload directive and default handlers for 37 // File Upload events: 38 .provider('fileUpload', function () { 39 var scopeEvalAsync = function (expression) { 40 var scope = angular.element(this) 41 .fileupload('option', 'scope'); 42 // Schedule a new $digest cycle if not already inside of one 43 // and evaluate the given expression: 44 scope.$evalAsync(expression); 45 }, 46 addFileMethods = function (scope, data) { 47 var files = data.files, 48 file = files[0]; 49 angular.forEach(files, function (file, index) { 50 file._index = index; 51 file.$state = function () { 52 return data.state(); 53 }; 54 file.$processing = function () { 55 return data.processing(); 56 }; 57 file.$progress = function () { 58 return data.progress(); 59 }; 60 file.$response = function () { 61 return data.response(); 62 }; 63 }); 64 file.$submit = function () { 65 if (!file.error) { 66 return data.submit(); 67 } 68 }; 69 file.$cancel = function () { 70 return data.abort(); 71 }; 72 }, 73 $config; 74 $config = this.defaults = { 75 handleResponse: function (e, data) { 76 var files = data.result && data.result.files; 77 if (files) { 78 data.scope.replace(data.files, files); 79 } else if (data.errorThrown || 80 data.textStatus === 'error') { 81 data.files[0].error = data.errorThrown || 82 data.textStatus; 83 } 84 }, 85 add: function (e, data) { 86 if (e.isDefaultPrevented()) { 87 return false; 88 } 89 var scope = data.scope, 90 filesCopy = []; 91 angular.forEach(data.files, function (file) { 92 filesCopy.push(file); 93 }); 94 scope.$apply(function () { 95 addFileMethods(scope, data); 96 var method = scope.option('prependFiles') ? 97 'unshift' : 'push'; 98 Array.prototype[method].apply(scope.queue, data.files); 99 }); 100 data.process(function () { 101 return scope.process(data); 102 }).always(function () { 103 scope.$apply(function () { 104 addFileMethods(scope, data); 105 scope.replace(filesCopy, data.files); 106 }); 107 }).then(function () { 108 if ((scope.option('autoUpload') || 109 data.autoUpload) && 110 data.autoUpload !== false) { 111 data.submit(); 112 } 113 }); 114 }, 115 progress: function (e, data) { 116 if (e.isDefaultPrevented()) { 117 return false; 118 } 119 data.scope.$apply(); 120 }, 121 done: function (e, data) { 122 if (e.isDefaultPrevented()) { 123 return false; 124 } 125 var that = this; 126 data.scope.$apply(function () { 127 data.handleResponse.call(that, e, data); 128 }); 129 }, 130 fail: function (e, data) { 131 if (e.isDefaultPrevented()) { 132 return false; 133 } 134 var that = this, 135 scope = data.scope; 136 if (data.errorThrown === 'abort') { 137 scope.clear(data.files); 138 return; 139 } 140 scope.$apply(function () { 141 data.handleResponse.call(that, e, data); 142 }); 143 }, 144 stop: scopeEvalAsync, 145 processstart: scopeEvalAsync, 146 processstop: scopeEvalAsync, 147 getNumberOfFiles: function () { 148 var scope = this.scope; 149 return scope.queue.length - scope.processing(); 150 }, 151 dataType: 'json', 152 autoUpload: false 153 }; 154 this.$get = [ 155 function () { 156 return { 157 defaults: $config 158 }; 159 } 160 ]; 161 }) 162 163 // Format byte numbers to readable presentations: 164 .provider('formatFileSizeFilter', function () { 165 var $config = { 166 // Byte units following the IEC format 167 // http://en.wikipedia.org/wiki/Kilobyte 168 units: [ 169 {size: 1000000000, suffix: ' GB'}, 170 {size: 1000000, suffix: ' MB'}, 171 {size: 1000, suffix: ' KB'} 172 ] 173 }; 174 this.defaults = $config; 175 this.$get = function () { 176 return function (bytes) { 177 if (!angular.isNumber(bytes)) { 178 return ''; 179 } 180 var unit = true, 181 i = 0, 182 prefix, 183 suffix; 184 while (unit) { 185 unit = $config.units[i]; 186 prefix = unit.prefix || ''; 187 suffix = unit.suffix || ''; 188 if (i === $config.units.length - 1 || bytes >= unit.size) { 189 return prefix + (bytes / unit.size).toFixed(2) + suffix; 190 } 191 i += 1; 192 } 193 }; 194 }; 195 }) 196 197 // The FileUploadController initializes the fileupload widget and 198 // provides scope methods to control the File Upload functionality: 199 .controller('FileUploadController', [ 200 '$scope', '$element', '$attrs', '$window', 'fileUpload', 201 function ($scope, $element, $attrs, $window, fileUpload) { 202 var uploadMethods = { 203 progress: function () { 204 return $element.fileupload('progress'); 205 }, 206 active: function () { 207 return $element.fileupload('active'); 208 }, 209 option: function (option, data) { 210 if (arguments.length === 1) { 211 return $element.fileupload('option', option); 212 } 213 $element.fileupload('option', option, data); 214 }, 215 add: function (data) { 216 return $element.fileupload('add', data); 217 }, 218 send: function (data) { 219 return $element.fileupload('send', data); 220 }, 221 process: function (data) { 222 return $element.fileupload('process', data); 223 }, 224 processing: function (data) { 225 return $element.fileupload('processing', data); 226 } 227 }; 228 $scope.disabled = !$window.jQuery.support.fileInput; 229 $scope.queue = $scope.queue || []; 230 $scope.clear = function (files) { 231 var queue = this.queue, 232 i = queue.length, 233 file = files, 234 length = 1; 235 if (angular.isArray(files)) { 236 file = files[0]; 237 length = files.length; 238 } 239 while (i) { 240 i -= 1; 241 if (queue[i] === file) { 242 return queue.splice(i, length); 243 } 244 } 245 }; 246 $scope.replace = function (oldFiles, newFiles) { 247 var queue = this.queue, 248 file = oldFiles[0], 249 i, 250 j; 251 for (i = 0; i < queue.length; i += 1) { 252 if (queue[i] === file) { 253 for (j = 0; j < newFiles.length; j += 1) { 254 queue[i + j] = newFiles[j]; 255 } 256 return; 257 } 258 } 259 }; 260 $scope.applyOnQueue = function (method) { 261 var list = this.queue.slice(0), 262 i, 263 file; 264 for (i = 0; i < list.length; i += 1) { 265 file = list[i]; 266 if (file[method]) { 267 file[method](); 268 } 269 } 270 }; 271 $scope.submit = function () { 272 this.applyOnQueue('$submit'); 273 }; 274 $scope.cancel = function () { 275 this.applyOnQueue('$cancel'); 276 }; 277 // Add upload methods to the scope: 278 angular.extend($scope, uploadMethods); 279 // The fileupload widget will initialize with 280 // the options provided via "data-"-parameters, 281 // as well as those given via options object: 282 $element.fileupload(angular.extend( 283 {scope: $scope}, 284 fileUpload.defaults 285 )).on('fileuploadadd', function (e, data) { 286 data.scope = $scope; 287 }).on('fileuploadfail', function (e, data) { 288 if (data.errorThrown === 'abort') { 289 return; 290 } 291 if (data.dataType && 292 data.dataType.indexOf('json') === data.dataType.length - 4) { 293 try { 294 data.result = angular.fromJson(data.jqXHR.responseText); 295 } catch (ignore) {} 296 } 297 }).on([ 298 'fileuploadadd', 299 'fileuploadsubmit', 300 'fileuploadsend', 301 'fileuploaddone', 302 'fileuploadfail', 303 'fileuploadalways', 304 'fileuploadprogress', 305 'fileuploadprogressall', 306 'fileuploadstart', 307 'fileuploadstop', 308 'fileuploadchange', 309 'fileuploadpaste', 310 'fileuploaddrop', 311 'fileuploaddragover', 312 'fileuploadchunksend', 313 'fileuploadchunkdone', 314 'fileuploadchunkfail', 315 'fileuploadchunkalways', 316 'fileuploadprocessstart', 317 'fileuploadprocess', 318 'fileuploadprocessdone', 319 'fileuploadprocessfail', 320 'fileuploadprocessalways', 321 'fileuploadprocessstop' 322 ].join(' '), function (e, data) { 323 if ($scope.$emit(e.type, data).defaultPrevented) { 324 e.preventDefault(); 325 } 326 }).on('remove', function () { 327 // Remove upload methods from the scope, 328 // when the widget is removed: 329 var method; 330 for (method in uploadMethods) { 331 if (uploadMethods.hasOwnProperty(method)) { 332 delete $scope[method]; 333 } 334 } 335 }); 336 // Observe option changes: 337 $scope.$watch( 338 $attrs.fileUpload, 339 function (newOptions) { 340 if (newOptions) { 341 $element.fileupload('option', newOptions); 342 } 343 } 344 ); 345 } 346 ]) 347 348 // Provide File Upload progress feedback: 349 .controller('FileUploadProgressController', [ 350 '$scope', '$attrs', '$parse', 351 function ($scope, $attrs, $parse) { 352 var fn = $parse($attrs.fileUploadProgress), 353 update = function () { 354 var progress = fn($scope); 355 if (!progress || !progress.total) { 356 return; 357 } 358 $scope.num = Math.floor( 359 progress.loaded / progress.total * 100 360 ); 361 }; 362 update(); 363 $scope.$watch( 364 $attrs.fileUploadProgress + '.loaded', 365 function (newValue, oldValue) { 366 if (newValue !== oldValue) { 367 update(); 368 } 369 } 370 ); 371 } 372 ]) 373 374 // Display File Upload previews: 375 .controller('FileUploadPreviewController', [ 376 '$scope', '$element', '$attrs', 377 function ($scope, $element, $attrs) { 378 $scope.$watch( 379 $attrs.fileUploadPreview + '.preview', 380 function (preview) { 381 $element.empty(); 382 if (preview) { 383 $element.append(preview); 384 } 385 } 386 ); 387 } 388 ]) 389 390 .directive('fileUpload', function () { 391 return { 392 controller: 'FileUploadController', 393 scope: true 394 }; 395 }) 396 397 .directive('fileUploadProgress', function () { 398 return { 399 controller: 'FileUploadProgressController', 400 scope: true 401 }; 402 }) 403 404 .directive('fileUploadPreview', function () { 405 return { 406 controller: 'FileUploadPreviewController' 407 }; 408 }) 409 410 // Enhance the HTML5 download attribute to 411 // allow drag&drop of files to the desktop: 412 .directive('download', function () { 413 return function (scope, elm) { 414 elm.on('dragstart', function (e) { 415 try { 416 e.originalEvent.dataTransfer.setData( 417 'DownloadURL', 418 [ 419 'application/octet-stream', 420 elm.prop('download'), 421 elm.prop('href') 422 ].join(':') 423 ); 424 } catch (ignore) {} 425 }); 426 }; 427 }); 428 429 }));