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