/** * @description * var app = angular.module('App', ['flow.provider'], function(flowFactoryProvider){ * flowFactoryProvider.defaults = {target: '/'}; * }); * @name flowFactoryProvider */ angular.module('flow.provider', []) .provider('flowFactory', function() { 'use strict'; /** * Define the default properties for flow.js * @name flowFactoryProvider.defaults * @type {Object} */ this.defaults = {}; /** * Flow, MaybeFlow or NotFlow * @name flowFactoryProvider.factory * @type {function} * @return {Flow} */ this.factory = function (options) { return new Flow(options); }; /** * Define the default events * @name flowFactoryProvider.events * @type {Array} * @private */ this.events = []; /** * Add default events * @name flowFactoryProvider.on * @function * @param {string} event * @param {Function} callback */ this.on = function (event, callback) { this.events.push([event, callback]); }; this.$get = function() { var fn = this.factory; var defaults = this.defaults; var events = this.events; return { 'create': function(opts) { // combine default options with global options and options var flow = fn(angular.extend({}, defaults, opts)); angular.forEach(events, function (event) { flow.on(event[0], event[1]); }); return flow; } }; }; }); angular.module('flow.init', ['flow.provider']) .controller('flowCtrl', ['$scope', '$attrs', '$parse', 'flowFactory', function ($scope, $attrs, $parse, flowFactory) { var options = angular.extend({}, $scope.$eval($attrs.flowInit)); // use existing flow object or create a new one var flow = $scope.$eval($attrs.flowObject) || flowFactory.create(options); flow.on('catchAll', function (eventName) { var args = Array.prototype.slice.call(arguments); args.shift(); var event = $scope.$broadcast.apply($scope, ['flow::' + eventName, flow].concat(args)); if ({ 'progress':1, 'filesSubmitted':1, 'fileSuccess': 1, 'fileError': 1, 'complete': 1 }[eventName]) { $scope.$apply(); } if (event.defaultPrevented) { return false; } }); $scope.$flow = flow; if ($attrs.hasOwnProperty('flowName')) { $parse($attrs.flowName).assign($scope, flow); $scope.$on('$destroy', function () { $parse($attrs.flowName).assign($scope); }); } }]) .directive('flowInit', [function() { return { scope: true, controller: 'flowCtrl' }; }]); angular.module('flow.btn', ['flow.init']) .directive('flowBtn', [function() { return { 'restrict': 'EA', 'scope': false, 'require': '^flowInit', 'link': function(scope, element, attrs) { var isDirectory = attrs.hasOwnProperty('flowDirectory'); var isSingleFile = attrs.hasOwnProperty('flowSingleFile'); var inputAttrs = attrs.hasOwnProperty('flowAttrs') && scope.$eval(attrs.flowAttrs); scope.$flow.assignBrowse(element, isDirectory, isSingleFile, inputAttrs); } }; }]); angular.module('flow.dragEvents', ['flow.init']) /** * @name flowPreventDrop * Prevent loading files then dropped on element */ .directive('flowPreventDrop', function() { return { 'scope': false, 'link': function(scope, element, attrs) { element.bind('drop dragover', function (event) { event.preventDefault(); }); } }; }) /** * @name flowDragEnter * executes `flowDragEnter` and `flowDragLeave` events */ .directive('flowDragEnter', ['$timeout', function($timeout) { return { 'scope': false, 'link': function(scope, element, attrs) { var promise; var enter = false; element.bind('dragover', function (event) { if (!isFileDrag(event)) { return ; } if (!enter) { scope.$apply(attrs.flowDragEnter); enter = true; } $timeout.cancel(promise); event.preventDefault(); }); element.bind('dragleave drop', function (event) { $timeout.cancel(promise); promise = $timeout(function () { scope.$eval(attrs.flowDragLeave); promise = null; enter = false; }, 100); }); function isFileDrag(dragEvent) { var fileDrag = false; var dataTransfer = dragEvent.dataTransfer || dragEvent.originalEvent.dataTransfer; angular.forEach(dataTransfer && dataTransfer.types, function(val) { if (val === 'Files') { fileDrag = true; } }); return fileDrag; } } }; }]); angular.module('flow.drop', ['flow.init']) .directive('flowDrop', function() { return { 'scope': false, 'require': '^flowInit', 'link': function(scope, element, attrs) { if (attrs.flowDropEnabled) { scope.$watch(attrs.flowDropEnabled, function (value) { if (value) { assignDrop(); } else { unAssignDrop(); } }); } else { assignDrop(); } function assignDrop() { scope.$flow.assignDrop(element); } function unAssignDrop() { scope.$flow.unAssignDrop(element); } } }; }); !function (angular) {'use strict'; var module = angular.module('flow.events', ['flow.init']); var events = { fileSuccess: ['$file', '$message'], fileProgress: ['$file'], fileAdded: ['$file', '$event'], filesAdded: ['$files', '$event'], filesSubmitted: ['$files', '$event'], fileRetry: ['$file'], fileError: ['$file', '$message'], uploadStart: [], complete: [], progress: [], error: ['$message', '$file'] }; angular.forEach(events, function (eventArgs, eventName) { var name = 'flow' + capitaliseFirstLetter(eventName); if (name == 'flowUploadStart') { name = 'flowUploadStarted';// event alias } module.directive(name, [function() { return { require: '^flowInit', controller: ['$scope', '$attrs', function ($scope, $attrs) { $scope.$on('flow::' + eventName, function () { var funcArgs = Array.prototype.slice.call(arguments); var event = funcArgs.shift();// remove angular event // remove flow object and ignore event if it is from parent directive if ($scope.$flow !== funcArgs.shift()) { return ; } var args = {}; angular.forEach(eventArgs, function(value, key) { args[value] = funcArgs[key]; }); if ($scope.$eval($attrs[name], args) === false) { event.preventDefault(); } }); }] }; }]); }); function capitaliseFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } }(angular); angular.module('flow.img', ['flow.init']) .directive('flowImg', [function() { return { 'scope': false, 'require': '^flowInit', 'link': function(scope, element, attrs) { var file = attrs.flowImg; scope.$watch(file, function (file) { if (!file) { return ; } var fileReader = new FileReader(); fileReader.readAsDataURL(file.file); fileReader.onload = function (event) { scope.$apply(function () { attrs.$set('src', event.target.result); }); }; }); } }; }]); angular.module('flow.transfers', ['flow.init']) .directive('flowTransfers', [function() { return { 'scope': true, 'require': '^flowInit', 'link': function(scope) { scope.transfers = scope.$flow.files; } }; }]); angular.module('flow', ['flow.provider', 'flow.init', 'flow.events', 'flow.btn', 'flow.drop', 'flow.transfers', 'flow.img', 'flow.dragEvents']);