Razique Mahroua
2019-11-28 1759c24ad2d2b35ec5c756e3dd3a60185fe944b7
commit | author | age
1759c2 1 /**
RM 2  * angular-strap
3  * @version v2.0.3 - 2014-05-30
4  * @link http://mgcrea.github.io/angular-strap
5  * @author Olivier Louvignes (olivier@mg-crea.com)
6  * @license MIT License, http://www.opensource.org/licenses/MIT
7  */
8 'use strict';
9 angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions']).provider('$modal', function () {
10   var defaults = this.defaults = {
11       animation: 'am-fade',
12       backdropAnimation: 'am-fade',
13       prefixClass: 'modal',
14       prefixEvent: 'modal',
15       placement: 'top',
16       template: 'modal/modal.tpl.html',
17       contentTemplate: false,
18       container: false,
19       element: null,
20       backdrop: true,
21       keyboard: true,
22       html: false,
23       show: true
24     };
25   this.$get = [
26     '$window',
27     '$rootScope',
28     '$compile',
29     '$q',
30     '$templateCache',
31     '$http',
32     '$animate',
33     '$timeout',
34     '$sce',
35     'dimensions',
36     function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {
37       var forEach = angular.forEach;
38       var trim = String.prototype.trim;
39       var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
40       var bodyElement = angular.element($window.document.body);
41       var htmlReplaceRegExp = /ng-bind="/gi;
42       function ModalFactory(config) {
43         var $modal = {};
44         // Common vars
45         var options = $modal.$options = angular.extend({}, defaults, config);
46         $modal.$promise = fetchTemplate(options.template);
47         var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();
48         if (!options.element && !options.container) {
49           options.container = 'body';
50         }
51         // Support scope as string options
52         forEach([
53           'title',
54           'content'
55         ], function (key) {
56           if (options[key])
57             scope[key] = $sce.trustAsHtml(options[key]);
58         });
59         // Provide scope helpers
60         scope.$hide = function () {
61           scope.$$postDigest(function () {
62             $modal.hide();
63           });
64         };
65         scope.$show = function () {
66           scope.$$postDigest(function () {
67             $modal.show();
68           });
69         };
70         scope.$toggle = function () {
71           scope.$$postDigest(function () {
72             $modal.toggle();
73           });
74         };
75         // Support contentTemplate option
76         if (options.contentTemplate) {
77           $modal.$promise = $modal.$promise.then(function (template) {
78             var templateEl = angular.element(template);
79             return fetchTemplate(options.contentTemplate).then(function (contentTemplate) {
80               var contentEl = findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);
81               // Drop the default footer as you probably don't want it if you use a custom contentTemplate
82               if (!config.template)
83                 contentEl.next().remove();
84               return templateEl[0].outerHTML;
85             });
86           });
87         }
88         // Fetch, compile then initialize modal
89         var modalLinker, modalElement;
90         var backdropElement = angular.element('<div class="' + options.prefixClass + '-backdrop"/>');
91         $modal.$promise.then(function (template) {
92           if (angular.isObject(template))
93             template = template.data;
94           if (options.html)
95             template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
96           template = trim.apply(template);
97           modalLinker = $compile(template);
98           $modal.init();
99         });
100         $modal.init = function () {
101           // Options: show
102           if (options.show) {
103             scope.$$postDigest(function () {
104               $modal.show();
105             });
106           }
107         };
108         $modal.destroy = function () {
109           // Remove element
110           if (modalElement) {
111             modalElement.remove();
112             modalElement = null;
113           }
114           if (backdropElement) {
115             backdropElement.remove();
116             backdropElement = null;
117           }
118           // Destroy scope
119           scope.$destroy();
120         };
121         $modal.show = function () {
122           scope.$emit(options.prefixEvent + '.show.before', $modal);
123           var parent = options.container ? findElement(options.container) : null;
124           var after = options.container ? null : options.element;
125           // Fetch a cloned element linked from template
126           modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) {
127           });
128           // Set the initial positioning.
129           modalElement.css({ display: 'block' }).addClass(options.placement);
130           // Options: animation
131           if (options.animation) {
132             if (options.backdrop) {
133               backdropElement.addClass(options.backdropAnimation);
134             }
135             modalElement.addClass(options.animation);
136           }
137           if (options.backdrop) {
138             $animate.enter(backdropElement, bodyElement, null, function () {
139             });
140           }
141           $animate.enter(modalElement, parent, after, function () {
142             scope.$emit(options.prefixEvent + '.show', $modal);
143           });
144           scope.$isShown = true;
145           scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest();
146           // Focus once the enter-animation has started
147           // Weird PhantomJS bug hack
148           var el = modalElement[0];
149           requestAnimationFrame(function () {
150             el.focus();
151           });
152           bodyElement.addClass(options.prefixClass + '-open');
153           if (options.animation) {
154             bodyElement.addClass(options.prefixClass + '-with-' + options.animation);
155           }
156           // Bind events
157           if (options.backdrop) {
158             modalElement.on('click', hideOnBackdropClick);
159             backdropElement.on('click', hideOnBackdropClick);
160           }
161           if (options.keyboard) {
162             modalElement.on('keyup', $modal.$onKeyUp);
163           }
164         };
165         $modal.hide = function () {
166           scope.$emit(options.prefixEvent + '.hide.before', $modal);
167           $animate.leave(modalElement, function () {
168             scope.$emit(options.prefixEvent + '.hide', $modal);
169             bodyElement.removeClass(options.prefixClass + '-open');
170             if (options.animation) {
171               bodyElement.addClass(options.prefixClass + '-with-' + options.animation);
172             }
173           });
174           if (options.backdrop) {
175             $animate.leave(backdropElement, function () {
176             });
177           }
178           scope.$isShown = false;
179           scope.$$phase || scope.$root && scope.$root.$$phase || scope.$digest();
180           // Unbind events
181           if (options.backdrop) {
182             modalElement.off('click', hideOnBackdropClick);
183             backdropElement.off('click', hideOnBackdropClick);
184           }
185           if (options.keyboard) {
186             modalElement.off('keyup', $modal.$onKeyUp);
187           }
188         };
189         $modal.toggle = function () {
190           scope.$isShown ? $modal.hide() : $modal.show();
191         };
192         $modal.focus = function () {
193           modalElement[0].focus();
194         };
195         // Protected methods
196         $modal.$onKeyUp = function (evt) {
197           evt.which === 27 && $modal.hide();
198         };
199         // Private methods
200         function hideOnBackdropClick(evt) {
201           if (evt.target !== evt.currentTarget)
202             return;
203           options.backdrop === 'static' ? $modal.focus() : $modal.hide();
204         }
205         return $modal;
206       }
207       // Helper functions
208       function findElement(query, element) {
209         return angular.element((element || document).querySelectorAll(query));
210       }
211       function fetchTemplate(template) {
212         return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) {
213           if (angular.isObject(res)) {
214             $templateCache.put(template, res.data);
215             return res.data;
216           }
217           return res;
218         });
219       }
220       return ModalFactory;
221     }
222   ];
223 }).directive('bsModal', [
224   '$window',
225   '$location',
226   '$sce',
227   '$modal',
228   function ($window, $location, $sce, $modal) {
229     return {
230       restrict: 'EAC',
231       scope: true,
232       link: function postLink(scope, element, attr, transclusion) {
233         // Directive options
234         var options = {
235             scope: scope,
236             element: element,
237             show: false
238           };
239         angular.forEach([
240           'template',
241           'contentTemplate',
242           'placement',
243           'backdrop',
244           'keyboard',
245           'html',
246           'container',
247           'animation'
248         ], function (key) {
249           if (angular.isDefined(attr[key]))
250             options[key] = attr[key];
251         });
252         // Support scope as data-attrs
253         angular.forEach([
254           'title',
255           'content'
256         ], function (key) {
257           attr[key] && attr.$observe(key, function (newValue, oldValue) {
258             scope[key] = $sce.trustAsHtml(newValue);
259           });
260         });
261         // Support scope as an object
262         attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) {
263           if (angular.isObject(newValue)) {
264             angular.extend(scope, newValue);
265           } else {
266             scope.content = newValue;
267           }
268         }, true);
269         // Initialize modal
270         var modal = $modal(options);
271         // Trigger
272         element.on(attr.trigger || 'click', modal.toggle);
273         // Garbage collection
274         scope.$on('$destroy', function () {
275           modal.destroy();
276           options = null;
277           modal = null;
278         });
279       }
280     };
281   }
282 ]);