text changes to registration mail content
[namibia] / public / js / vendor / bootstrap-modalmanager.js
1 /* ===========================================================
2  * bootstrap-modalmanager.js v2.1
3  * ===========================================================
4  * Copyright 2012 Jordan Schroter.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * ========================================================== */
18
19 !function ($) {
20
21         "use strict"; // jshint ;_;
22
23         /* MODAL MANAGER CLASS DEFINITION
24         * ====================== */
25
26         var ModalManager = function (element, options) {
27                 this.init(element, options);
28         };
29
30         ModalManager.prototype = {
31
32                 constructor: ModalManager,
33
34                 init: function (element, options) {
35                         this.$element = $(element);
36                         this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options == 'object' && options);
37                         this.stack = [];
38                         this.backdropCount = 0;
39
40                         if (this.options.resize) {
41                                 var resizeTimeout,
42                                         that = this;
43
44                                 $(window).on('resize.modal', function(){
45                                         resizeTimeout && clearTimeout(resizeTimeout);
46                                         resizeTimeout = setTimeout(function(){
47                                                 for (var i = 0; i < that.stack.length; i++){
48                                                         that.stack[i].isShown && that.stack[i].layout();
49                                                 }
50                                         }, 10);
51                                 });
52                         }
53                 },
54
55                 createModal: function (element, options) {
56                         $(element).modal($.extend({ manager: this }, options));
57                 },
58
59                 appendModal: function (modal) {
60                         this.stack.push(modal);
61
62                         var that = this;
63
64                         modal.$element.on('show.modalmanager', targetIsSelf(function (e) {
65
66                                 var showModal = function(){
67                                         modal.isShown = true;
68
69                                         var transition = $.support.transition && modal.$element.hasClass('fade');
70
71                                         that.$element
72                                                 .toggleClass('modal-open', that.hasOpenModal())
73                                                 .toggleClass('page-overflow', $(window).height() < that.$element.height());
74
75                                         modal.$parent = modal.$element.parent();
76
77                                         modal.$container = that.createContainer(modal);
78
79                                         modal.$element.appendTo(modal.$container);
80
81                                         that.backdrop(modal, function () {
82
83                                                 modal.$element.show();
84
85                                                 if (transition) {       
86                                                         //modal.$element[0].style.display = 'run-in';       
87                                                         modal.$element[0].offsetWidth;
88                                                         //modal.$element.one($.support.transition.end, function () { modal.$element[0].style.display = 'block' });  
89                                                 }
90                                                 
91                                                 modal.layout();
92
93                                                 modal.$element
94                                                         .addClass('in')
95                                                         .attr('aria-hidden', false);
96
97                                                 var complete = function () {
98                                                         that.setFocus();
99                                                         modal.$element.trigger('shown');
100                                                 };
101
102                                                 transition ?
103                                                         modal.$element.one($.support.transition.end, complete) :
104                                                         complete();
105                                         });
106                                 };
107
108                                 modal.options.replace ?
109                                         that.replace(showModal) :
110                                         showModal();
111                         }));
112
113                         modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
114
115                                 that.backdrop(modal);
116
117                                 if (modal.$backdrop){
118                                         $.support.transition && modal.$element.hasClass('fade') ?
119                                                 modal.$backdrop.one($.support.transition.end, function () { that.destroyModal(modal) }) :
120                                                 that.destroyModal(modal);
121                                 } else {
122                                         that.destroyModal(modal);
123                                 }
124
125                         }));
126
127                         modal.$element.on('destroy.modalmanager', targetIsSelf(function (e) {
128                                 that.removeModal(modal);
129                         }));
130
131                 },
132
133                 destroyModal: function (modal) {
134
135                         modal.destroy();
136
137                         var hasOpenModal = this.hasOpenModal();
138
139                         this.$element.toggleClass('modal-open', hasOpenModal);
140
141                         if (!hasOpenModal){
142                                 this.$element.removeClass('page-overflow');
143                         }
144
145                         this.removeContainer(modal);
146
147                         this.setFocus();
148                 },
149
150                 hasOpenModal: function () {
151                         for (var i = 0; i < this.stack.length; i++){
152                                 if (this.stack[i].isShown) return true;
153                         }
154
155                         return false;
156                 },
157
158                 setFocus: function () {
159                         var topModal;
160
161                         for (var i = 0; i < this.stack.length; i++){
162                                 if (this.stack[i].isShown) topModal = this.stack[i];
163                         }
164
165                         if (!topModal) return;
166
167                         topModal.focus();
168
169                 },
170
171                 removeModal: function (modal) {
172                         modal.$element.off('.modalmanager');
173                         if (modal.$backdrop) this.removeBackdrop.call(modal);
174                         this.stack.splice(this.getIndexOfModal(modal), 1);
175                 },
176
177                 getModalAt: function (index) {
178                         return this.stack[index];
179                 },
180
181                 getIndexOfModal: function (modal) {
182                         for (var i = 0; i < this.stack.length; i++){
183                                 if (modal === this.stack[i]) return i;
184                         }
185                 },
186
187                 replace: function (callback) {
188                         var topModal;
189
190                         for (var i = 0; i < this.stack.length; i++){
191                                 if (this.stack[i].isShown) topModal = this.stack[i];
192                         }
193
194                         if (topModal) {
195                                 this.$backdropHandle = topModal.$backdrop;
196                                 topModal.$backdrop = null;
197
198                                 callback && topModal.$element.one('hidden',
199                                         targetIsSelf( $.proxy(callback, this) ));
200
201                                 topModal.hide();
202                         } else if (callback) {
203                                 callback();
204                         }
205                 },
206
207                 removeBackdrop: function (modal) {
208                         modal.$backdrop.remove();
209                         modal.$backdrop = null;
210                 },
211
212                 createBackdrop: function (animate) {
213                         var $backdrop;
214
215                         if (!this.$backdropHandle) {
216                                 $backdrop = $('<div class="modal-backdrop ' + animate + '" />')
217                                         .appendTo(this.$element);
218                         } else {
219                                 $backdrop = this.$backdropHandle;
220                                 $backdrop.off('.modalmanager');
221                                 this.$backdropHandle = null;
222                                 this.isLoading && this.removeSpinner();
223                         }
224
225                         return $backdrop
226                 },
227
228                 removeContainer: function (modal) {
229                         modal.$container.remove();
230                         modal.$container = null;
231                 },
232
233                 createContainer: function (modal) {
234                         var $container;
235
236                         $container = $('<div class="modal-scrollable">')
237                                 .css('z-index', getzIndex( 'modal',
238                                         modal ? this.getIndexOfModal(modal) : this.stack.length ))
239                                 .appendTo(this.$element);
240
241                         if (modal && modal.options.backdrop != 'static') {
242                                 $container.on('click.modal', targetIsSelf(function (e) {
243                                         modal.hide();
244                                 }));
245                         } else if (modal) {
246                                 $container.on('click.modal', targetIsSelf(function (e) {
247                                         modal.attention();
248                                 }));
249                         }
250
251                         return $container;
252
253                 },
254
255                 backdrop: function (modal, callback) {
256                         var animate = modal.$element.hasClass('fade') ? 'fade' : '',
257                                 showBackdrop = modal.options.backdrop &&
258                                         this.backdropCount < this.options.backdropLimit;
259
260                         if (modal.isShown && showBackdrop) {
261                                 var doAnimate = $.support.transition && animate && !this.$backdropHandle;
262
263                                 modal.$backdrop = this.createBackdrop(animate);
264
265                                 modal.$backdrop.css('z-index', getzIndex( 'backdrop', this.getIndexOfModal(modal) ));
266
267                                 if (doAnimate) modal.$backdrop[0].offsetWidth; // force reflow
268
269                                 modal.$backdrop.addClass('in');
270
271                                 this.backdropCount += 1;
272
273                                 doAnimate ?
274                                         modal.$backdrop.one($.support.transition.end, callback) :
275                                         callback();
276
277                         } else if (!modal.isShown && modal.$backdrop) {
278                                 modal.$backdrop.removeClass('in');
279
280                                 this.backdropCount -= 1;
281
282                                 var that = this;
283
284                                 $.support.transition && modal.$element.hasClass('fade')?
285                                         modal.$backdrop.one($.support.transition.end, function () { that.removeBackdrop(modal) }) :
286                                         that.removeBackdrop(modal);
287
288                         } else if (callback) {
289                                 callback();
290                         }
291                 },
292
293                 removeSpinner: function(){
294                         this.$spinner && this.$spinner.remove();
295                         this.$spinner = null;
296                         this.isLoading = false;
297                 },
298
299                 removeLoading: function () {
300                         this.$backdropHandle && this.$backdropHandle.remove();
301                         this.$backdropHandle = null;
302                         this.removeSpinner();
303                 },
304
305                 loading: function (callback) {
306                         callback = callback || function () { };
307
308                         this.$element
309                                 .toggleClass('modal-open', !this.isLoading || this.hasOpenModal())
310                                 .toggleClass('page-overflow', $(window).height() < this.$element.height());
311
312                         if (!this.isLoading) {
313
314                                 this.$backdropHandle = this.createBackdrop('fade');
315
316                                 this.$backdropHandle[0].offsetWidth; // force reflow
317
318                                 this.$backdropHandle
319                                         .css('z-index', getzIndex('backdrop', this.stack.length))
320                                         .addClass('in');
321
322                                 var $spinner = $(this.options.spinner)
323                                         .css('z-index', getzIndex('modal', this.stack.length))
324                                         .appendTo(this.$element)
325                                         .addClass('in');
326
327                                 this.$spinner = $(this.createContainer())
328                                         .append($spinner)
329                                         .on('click.modalmanager', $.proxy(this.loading, this));
330
331                                 this.isLoading = true;
332
333                                 $.support.transition ?
334                                         this.$backdropHandle.one($.support.transition.end, callback) :
335                                         callback();
336
337                         } else if (this.isLoading && this.$backdropHandle) {
338                                 this.$backdropHandle.removeClass('in');
339
340                                 var that = this;
341                                 $.support.transition ?
342                                         this.$backdropHandle.one($.support.transition.end, function () { that.removeLoading() }) :
343                                         that.removeLoading();
344
345                         } else if (callback) {
346                                 callback(this.isLoading);
347                         }
348                 }
349         };
350
351         /* PRIVATE METHODS
352         * ======================= */
353
354         // computes and caches the zindexes
355         var getzIndex = (function () {
356                 var zIndexFactor,
357                         baseIndex = {};
358
359                 return function (type, pos) {
360
361                         if (typeof zIndexFactor === 'undefined'){
362                                 var $baseModal = $('<div class="modal hide" />').appendTo('body'),
363                                         $baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
364
365                                 baseIndex['modal'] = +$baseModal.css('z-index');
366                                 baseIndex['backdrop'] = +$baseBackdrop.css('z-index');
367                                 zIndexFactor = baseIndex['modal'] - baseIndex['backdrop'];
368
369                                 $baseModal.remove();
370                                 $baseBackdrop.remove();
371                                 $baseBackdrop = $baseModal = null;
372                         }
373
374                         return baseIndex[type] + (zIndexFactor * pos);
375
376                 }
377         }());
378
379         // make sure the event target is the modal itself in order to prevent
380         // other components such as tabsfrom triggering the modal manager.
381         // if Boostsrap namespaced events, this would not be needed.
382         function targetIsSelf(callback){
383                 return function (e) {
384                         if (this === e.target){
385                                 return callback.apply(this, arguments);
386                         }
387                 }
388         }
389
390
391         /* MODAL MANAGER PLUGIN DEFINITION
392         * ======================= */
393
394         $.fn.modalmanager = function (option, args) {
395                 return this.each(function () {
396                         var $this = $(this),
397                                 data = $this.data('modalmanager');
398
399                         if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)));
400                         if (typeof option === 'string') data[option].apply(data, [].concat(args))
401                 })
402         };
403
404         $.fn.modalmanager.defaults = {
405                 backdropLimit: 999,
406                 resize: true,
407                 spinner: '<div class="loading-spinner fade" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>'
408         };
409
410         $.fn.modalmanager.Constructor = ModalManager
411
412 }(jQuery);