Update JSON API
[src/app-framework-demo.git] / afm-client / bower_components / foundation-apps / js / angular / components / modal / modal.js
1 (function() {
2   'use strict';
3
4   angular.module('foundation.modal', ['foundation.core'])
5     .directive('zfModal', modalDirective)
6     .factory('ModalFactory', ModalFactory)
7   ;
8
9   FoundationModal.$inject = ['FoundationApi', 'ModalFactory'];
10
11   function FoundationModal(foundationApi, ModalFactory) {
12     var service    = {};
13
14     service.activate = activate;
15     service.deactivate = deactivate;
16     service.newModal = newModal;
17
18     return service;
19
20     //target should be element ID
21     function activate(target) {
22       foundationApi.publish(target, 'show');
23     }
24
25     //target should be element ID
26     function deactivate(target) {
27       foundationApi.publish(target, 'hide');
28     }
29
30     //new modal has to be controlled via the new instance
31     function newModal(config) {
32       return new ModalFactory(config);
33     }
34   }
35
36   modalDirective.$inject = ['FoundationApi'];
37
38   function modalDirective(foundationApi) {
39
40     var directive = {
41       restrict: 'EA',
42       templateUrl: 'components/modal/modal.html',
43       transclude: true,
44       scope: true,
45       replace: true,
46       compile: compile
47     };
48
49     return directive;
50
51     function compile(tElement, tAttrs, transclude) {
52       var type = 'modal';
53
54       return {
55         pre: preLink,
56         post: postLink
57       };
58
59       function preLink(scope, iElement, iAttrs, controller) {
60           iAttrs.$set('zf-closable', type);
61       }
62
63       function postLink(scope, element, attrs) {
64         var dialog = angular.element(element.children()[0]);
65
66         scope.active = scope.active || false;
67         scope.overlay = attrs.overlay === 'false' ? false : true;
68         scope.overlayClose = attrs.overlayClose === 'false' ? false : true;
69
70         var animationIn = attrs.animationIn || 'fadeIn';
71         var animationOut = attrs.animationOut || 'fadeOut';
72
73         var overlayIn = 'fadeIn';
74         var overlayOut = 'fadeOut';
75
76         scope.hideOverlay = function() {
77           if(scope.overlayClose) {
78             scope.hide();
79           }
80         };
81
82         scope.hide = function() {
83           scope.active = false;
84           animate();
85           return;
86         };
87
88         scope.show = function() {
89           scope.active = true;
90           animate();
91           dialog.tabIndex = -1;
92           dialog[0].focus();
93           return;
94         };
95
96         scope.toggle = function() {
97           scope.active = !scope.active;
98           animate();
99           return;
100         };
101
102         init();
103
104         //setup
105         foundationApi.subscribe(attrs.id, function(msg) {
106           if(msg === 'show' || msg === 'open') {
107             scope.show();
108           } else if (msg === 'close' || msg === 'hide') {
109             scope.hide();
110           } else if (msg === 'toggle') {
111             scope.toggle();
112           }
113
114           if (scope.$root && !scope.$root.$$phase) {
115             scope.$apply();
116           }
117
118           return;
119         });
120
121         function animate() {
122           //animate both overlay and dialog
123           if(!scope.overlay) {
124             element.css('background', 'transparent');
125           }
126
127           foundationApi.animate(element, scope.active, overlayIn, overlayOut);
128           foundationApi.animate(dialog, scope.active, animationIn, animationOut);
129         }
130
131         function init() {
132           if(scope.active) {
133             scope.show();
134           }
135         }
136       }
137     }
138   }
139
140   ModalFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', '$q', 'FoundationApi'];
141
142   function ModalFactory($http, $templateCache, $rootScope, $compile, $timeout, $q, foundationApi) {
143     return modalFactory;
144
145     function modalFactory(config) {
146       var self = this, //for prototype functions
147           container = angular.element(config.container || document.body),
148           id = config.id || foundationApi.generateUuid(),
149           attached = false,
150           destroyed = false,
151           html,
152           element,
153           fetched,
154           scope,
155           contentScope
156       ;
157
158       var props = [
159         'animationIn',
160         'animationOut',
161         'overlay',
162         'overlayClose'
163       ];
164
165       if(config.templateUrl) {
166         //get template
167         fetched = $http.get(config.templateUrl, {
168           cache: $templateCache
169         }).then(function (response) {
170           html = response.data;
171           assembleDirective();
172         });
173
174       } else if(config.template) {
175         //use provided template
176         fetched = true;
177         html = config.template;
178         assembleDirective();
179       }
180
181       self.activate = activate;
182       self.deactivate = deactivate;
183       self.toggle = toggle;
184       self.destroy = destroy;
185
186
187       return {
188         activate: activate,
189         deactivate: deactivate,
190         toggle: toggle,
191         destroy: destroy
192       };
193
194       function checkStatus() {
195         if(destroyed) {
196           throw "Error: Modal was destroyed. Delete the object and create a new ModalFactory instance."
197         }
198       }
199
200       function activate() {
201         checkStatus();
202         $timeout(function() {
203           init(true);
204           foundationApi.publish(id, 'show');
205         }, 0, false);
206       }
207
208       function deactivate() {
209         checkStatus();
210         $timeout(function() {
211           init(false);
212           foundationApi.publish(id, 'hide');
213         }, 0, false);
214       }
215
216       function toggle() {
217         checkStatus();
218         $timeout(function() {
219           init(true);
220           foundationApi.publish(id, 'toggle');
221         }, 0, false);
222       }
223
224       function init(state) {
225         $q.when(fetched).then(function() {
226           if(!attached && html.length > 0) {
227             var modalEl = container.append(element);
228
229             scope.active = state;
230             $compile(element)(scope);
231
232             attached = true;
233           }
234         });
235       }
236
237       function assembleDirective() {
238         // check for duplicate elements to prevent factory from cloning modals
239         if (document.getElementById(id)) {
240           return;
241         }
242
243         html = '<zf-modal id="' + id + '">' + html + '</zf-modal>';
244
245         element = angular.element(html);
246
247         scope = $rootScope.$new();
248
249         // account for directive attributes
250         for(var i = 0; i < props.length; i++) {
251           var prop = props[i];
252
253           if(config[prop]) {
254             switch (prop) {
255               case 'animationIn':
256                 element.attr('animation-in', config[prop]);
257                 break;
258               case 'animationOut':
259                 element.attr('animation-out', config[prop]);
260                 break;
261               default:
262                 element.attr(prop, config[prop]);
263             }
264           }
265         }
266         // access view scope variables
267         if (config.contentScope) {
268           contentScope = config.contentScope;
269           for (var prop in config.contentScope) {
270             if (config.contentScope.hasOwnProperty(prop)) {
271               scope[prop] = config.contentScope[prop];
272             }
273           }
274         }
275       }
276
277       function destroy() {
278         self.deactivate();
279         setTimeout(function() {
280           scope.$destroy();
281           element.remove();
282           destroyed = true;
283         }, 3000);
284         foundationApi.unsubscribe(id);
285       }
286
287     }
288
289   }
290
291 })();