ng-flow.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /**
  2. * @description
  3. * var app = angular.module('App', ['flow.provider'], function(flowFactoryProvider){
  4. * flowFactoryProvider.defaults = {target: '/'};
  5. * });
  6. * @name flowFactoryProvider
  7. */
  8. angular.module('flow.provider', [])
  9. .provider('flowFactory', function() {
  10. 'use strict';
  11. /**
  12. * Define the default properties for flow.js
  13. * @name flowFactoryProvider.defaults
  14. * @type {Object}
  15. */
  16. this.defaults = {};
  17. /**
  18. * Flow, MaybeFlow or NotFlow
  19. * @name flowFactoryProvider.factory
  20. * @type {function}
  21. * @return {Flow}
  22. */
  23. this.factory = function (options) {
  24. return new Flow(options);
  25. };
  26. /**
  27. * Define the default events
  28. * @name flowFactoryProvider.events
  29. * @type {Array}
  30. * @private
  31. */
  32. this.events = [];
  33. /**
  34. * Add default events
  35. * @name flowFactoryProvider.on
  36. * @function
  37. * @param {string} event
  38. * @param {Function} callback
  39. */
  40. this.on = function (event, callback) {
  41. this.events.push([event, callback]);
  42. };
  43. this.$get = function() {
  44. var fn = this.factory;
  45. var defaults = this.defaults;
  46. var events = this.events;
  47. return {
  48. 'create': function(opts) {
  49. // combine default options with global options and options
  50. var flow = fn(angular.extend({}, defaults, opts));
  51. angular.forEach(events, function (event) {
  52. flow.on(event[0], event[1]);
  53. });
  54. return flow;
  55. }
  56. };
  57. };
  58. });
  59. angular.module('flow.init', ['flow.provider'])
  60. .controller('flowCtrl', ['$scope', '$attrs', '$parse', 'flowFactory',
  61. function ($scope, $attrs, $parse, flowFactory) {
  62. var options = angular.extend({}, $scope.$eval($attrs.flowInit));
  63. // use existing flow object or create a new one
  64. var flow = $scope.$eval($attrs.flowObject) || flowFactory.create(options);
  65. flow.on('catchAll', function (eventName) {
  66. var args = Array.prototype.slice.call(arguments);
  67. args.shift();
  68. var event = $scope.$broadcast.apply($scope, ['flow::' + eventName, flow].concat(args));
  69. if ({
  70. 'progress':1, 'filesSubmitted':1, 'fileSuccess': 1, 'fileError': 1, 'complete': 1
  71. }[eventName]) {
  72. $scope.$apply();
  73. }
  74. if (event.defaultPrevented) {
  75. return false;
  76. }
  77. });
  78. $scope.$flow = flow;
  79. if ($attrs.hasOwnProperty('flowName')) {
  80. $parse($attrs.flowName).assign($scope, flow);
  81. $scope.$on('$destroy', function () {
  82. $parse($attrs.flowName).assign($scope);
  83. });
  84. }
  85. }])
  86. .directive('flowInit', [function() {
  87. return {
  88. scope: true,
  89. controller: 'flowCtrl'
  90. };
  91. }]);
  92. angular.module('flow.btn', ['flow.init'])
  93. .directive('flowBtn', [function() {
  94. return {
  95. 'restrict': 'EA',
  96. 'scope': false,
  97. 'require': '^flowInit',
  98. 'link': function(scope, element, attrs) {
  99. var isDirectory = attrs.hasOwnProperty('flowDirectory');
  100. var isSingleFile = attrs.hasOwnProperty('flowSingleFile');
  101. var inputAttrs = attrs.hasOwnProperty('flowAttrs') && scope.$eval(attrs.flowAttrs);
  102. scope.$flow.assignBrowse(element, isDirectory, isSingleFile, inputAttrs);
  103. }
  104. };
  105. }]);
  106. angular.module('flow.dragEvents', ['flow.init'])
  107. /**
  108. * @name flowPreventDrop
  109. * Prevent loading files then dropped on element
  110. */
  111. .directive('flowPreventDrop', function() {
  112. return {
  113. 'scope': false,
  114. 'link': function(scope, element, attrs) {
  115. element.bind('drop dragover', function (event) {
  116. event.preventDefault();
  117. });
  118. }
  119. };
  120. })
  121. /**
  122. * @name flowDragEnter
  123. * executes `flowDragEnter` and `flowDragLeave` events
  124. */
  125. .directive('flowDragEnter', ['$timeout', function($timeout) {
  126. return {
  127. 'scope': false,
  128. 'link': function(scope, element, attrs) {
  129. var promise;
  130. var enter = false;
  131. element.bind('dragover', function (event) {
  132. if (!isFileDrag(event)) {
  133. return ;
  134. }
  135. if (!enter) {
  136. scope.$apply(attrs.flowDragEnter);
  137. enter = true;
  138. }
  139. $timeout.cancel(promise);
  140. event.preventDefault();
  141. });
  142. element.bind('dragleave drop', function (event) {
  143. $timeout.cancel(promise);
  144. promise = $timeout(function () {
  145. scope.$eval(attrs.flowDragLeave);
  146. promise = null;
  147. enter = false;
  148. }, 100);
  149. });
  150. function isFileDrag(dragEvent) {
  151. var fileDrag = false;
  152. var dataTransfer = dragEvent.dataTransfer || dragEvent.originalEvent.dataTransfer;
  153. angular.forEach(dataTransfer && dataTransfer.types, function(val) {
  154. if (val === 'Files') {
  155. fileDrag = true;
  156. }
  157. });
  158. return fileDrag;
  159. }
  160. }
  161. };
  162. }]);
  163. angular.module('flow.drop', ['flow.init'])
  164. .directive('flowDrop', function() {
  165. return {
  166. 'scope': false,
  167. 'require': '^flowInit',
  168. 'link': function(scope, element, attrs) {
  169. if (attrs.flowDropEnabled) {
  170. scope.$watch(attrs.flowDropEnabled, function (value) {
  171. if (value) {
  172. assignDrop();
  173. } else {
  174. unAssignDrop();
  175. }
  176. });
  177. } else {
  178. assignDrop();
  179. }
  180. function assignDrop() {
  181. scope.$flow.assignDrop(element);
  182. }
  183. function unAssignDrop() {
  184. scope.$flow.unAssignDrop(element);
  185. }
  186. }
  187. };
  188. });
  189. !function (angular) {'use strict';
  190. var module = angular.module('flow.events', ['flow.init']);
  191. var events = {
  192. fileSuccess: ['$file', '$message'],
  193. fileProgress: ['$file'],
  194. fileAdded: ['$file', '$event'],
  195. filesAdded: ['$files', '$event'],
  196. filesSubmitted: ['$files', '$event'],
  197. fileRetry: ['$file'],
  198. fileError: ['$file', '$message'],
  199. uploadStart: [],
  200. complete: [],
  201. progress: [],
  202. error: ['$message', '$file']
  203. };
  204. angular.forEach(events, function (eventArgs, eventName) {
  205. var name = 'flow' + capitaliseFirstLetter(eventName);
  206. if (name == 'flowUploadStart') {
  207. name = 'flowUploadStarted';// event alias
  208. }
  209. module.directive(name, [function() {
  210. return {
  211. require: '^flowInit',
  212. controller: ['$scope', '$attrs', function ($scope, $attrs) {
  213. $scope.$on('flow::' + eventName, function () {
  214. var funcArgs = Array.prototype.slice.call(arguments);
  215. var event = funcArgs.shift();// remove angular event
  216. // remove flow object and ignore event if it is from parent directive
  217. if ($scope.$flow !== funcArgs.shift()) {
  218. return ;
  219. }
  220. var args = {};
  221. angular.forEach(eventArgs, function(value, key) {
  222. args[value] = funcArgs[key];
  223. });
  224. if ($scope.$eval($attrs[name], args) === false) {
  225. event.preventDefault();
  226. }
  227. });
  228. }]
  229. };
  230. }]);
  231. });
  232. function capitaliseFirstLetter(string) {
  233. return string.charAt(0).toUpperCase() + string.slice(1);
  234. }
  235. }(angular);
  236. angular.module('flow.img', ['flow.init'])
  237. .directive('flowImg', [function() {
  238. return {
  239. 'scope': false,
  240. 'require': '^flowInit',
  241. 'link': function(scope, element, attrs) {
  242. var file = attrs.flowImg;
  243. scope.$watch(file, function (file) {
  244. if (!file) {
  245. return ;
  246. }
  247. var fileReader = new FileReader();
  248. fileReader.readAsDataURL(file.file);
  249. fileReader.onload = function (event) {
  250. scope.$apply(function () {
  251. attrs.$set('src', event.target.result);
  252. });
  253. };
  254. });
  255. }
  256. };
  257. }]);
  258. angular.module('flow.transfers', ['flow.init'])
  259. .directive('flowTransfers', [function() {
  260. return {
  261. 'scope': true,
  262. 'require': '^flowInit',
  263. 'link': function(scope) {
  264. scope.transfers = scope.$flow.files;
  265. }
  266. };
  267. }]);
  268. angular.module('flow', ['flow.provider', 'flow.init', 'flow.events', 'flow.btn',
  269. 'flow.drop', 'flow.transfers', 'flow.img', 'flow.dragEvents']);