src/ztfy/myams/resources/js/ext/bootstrap-modalmanager.js
changeset 155 e0fb6fd568eb
parent 118 c87d242a1176
equal deleted inserted replaced
154:0fff49179f6d 155:e0fb6fd568eb
    16  * limitations under the License.
    16  * limitations under the License.
    17  * ========================================================== */
    17  * ========================================================== */
    18 
    18 
    19 !function ($) {
    19 !function ($) {
    20 
    20 
    21 	"use strict"; // jshint ;_;
    21 	"use strict";  // jshint ;_;
    22 
    22 
    23 	/* MODAL MANAGER CLASS DEFINITION
    23 	/* MODAL MANAGER CLASS DEFINITION
    24 	 * ====================== */
    24 	 * ====================== */
    25 
    25 
    26 	var ModalManager = function (element, options) {
    26 	var ModalManager = function (element, options) {
    31 
    31 
    32 		constructor: ModalManager,
    32 		constructor: ModalManager,
    33 
    33 
    34 		init: function (element, options) {
    34 		init: function (element, options) {
    35 			this.$element = $(element);
    35 			this.$element = $(element);
    36 			this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options == 'object' && options);
    36 			this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options === 'object' && options);
    37 			this.stack = [];
    37 			this.stack = [];
    38 			this.backdropCount = 0;
    38 			this.backdropCount = 0;
    39 
    39 
    40 			if (this.options.resize) {
    40 			if (this.options.resize) {
    41 				var resizeTimeout,
    41 				var resizeTimeout,
    42 					that = this;
    42 					that = this;
    43 
    43 
    44 				$(window).on('resize.modal', function () {
    44 				$(window).on('resize.modal', function () {
    45 					resizeTimeout && clearTimeout(resizeTimeout);
    45 					if (resizeTimeout) {
       
    46 						clearTimeout(resizeTimeout);
       
    47 					}
    46 					resizeTimeout = setTimeout(function () {
    48 					resizeTimeout = setTimeout(function () {
    47 						for (var i = 0; i < that.stack.length; i++) {
    49 						for (var i = 0; i < that.stack.length; i++) {
    48 							that.stack[i].isShown && that.stack[i].layout();
    50 							if (that.stack[i].isShown) {
       
    51 								that.stack[i].layout();
       
    52 							}
    49 						}
    53 						}
    50 					}, 10);
    54 					}, 10);
    51 				});
    55 				});
    52 			}
    56 			}
    53 		},
    57 		},
    80 
    84 
    81 					that.backdrop(modal, function () {
    85 					that.backdrop(modal, function () {
    82 						modal.$element.show();
    86 						modal.$element.show();
    83 
    87 
    84 						if (transition) {
    88 						if (transition) {
    85 							//modal.$element[0].style.display = 'run-in';       
    89 							//modal.$element[0].style.display = 'run-in';
    86 							modal.$element[0].offsetWidth;
    90 							modal.$element[0].offsetWidth;
    87 							//modal.$element.one($.support.transition.end, function () { modal.$element[0].style.display = 'block' });  
    91 							//modal.$element.one($.support.transition.end, function () { modal.$element[0].style.display = 'block' });
    88 						}
    92 						}
    89 
    93 
    90 						modal.layout();
    94 						modal.layout();
    91 
    95 
    92 						modal.$element
    96 						modal.$element
    96 						var complete = function () {
   100 						var complete = function () {
    97 							that.setFocus();
   101 							that.setFocus();
    98 							modal.$element.trigger('shown');
   102 							modal.$element.trigger('shown');
    99 						};
   103 						};
   100 
   104 
   101 						transition ?
   105 						if (transition) {
   102 							modal.$element.one($.support.transition.end, complete) :
   106 							modal.$element.one($.support.transition.end, complete);
       
   107 						} else {
   103 							complete();
   108 							complete();
       
   109 						}
   104 					});
   110 					});
   105 				};
   111 				};
   106 
   112 
   107 				modal.options.replace ?
   113 				if (modal.options.replace) {
   108 					that.replace(showModal) :
   114 					that.replace(showModal);
       
   115 				} else {
   109 					showModal();
   116 					showModal();
       
   117 				}
   110 			}));
   118 			}));
   111 
   119 
   112 			modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
   120 			modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
   113 				that.backdrop(modal);
   121 				that.backdrop(modal);
   114 				// handle the case when a modal may have been removed from the dom before this callback executes
   122 				// handle the case when a modal may have been removed from the dom before this callback executes
   115 				if (!modal.$element.parent().length) {
   123 				if (!modal.$element.parent().length) {
   116 					that.destroyModal(modal);
   124 					that.destroyModal(modal);
   117 				} else if (modal.$backdrop) {
   125 				} else if (modal.$backdrop) {
   118 					var transition = $.support.transition && modal.$element.hasClass('fade');
   126 					var transition = $.support.transition && modal.$element.hasClass('fade');
   119 
   127 
   120 					// trigger a relayout due to firebox's buggy transition end event
   128 					// trigger a relayout due to firefox's buggy transition end event
   121 					if (transition)
   129 					if (transition) {
   122 						modal.$element[0].offsetWidth;
   130 						modal.$element[0].offsetWidth;
   123 					$.support.transition && modal.$element.hasClass('fade') ?
   131 					}
       
   132 					if ($.support.transition && modal.$element.hasClass('fade')) {
   124 						modal.$backdrop.one($.support.transition.end, function () {
   133 						modal.$backdrop.one($.support.transition.end, function () {
   125 							modal.destroy();
   134 							modal.destroy();
   126 						}) :
   135 						});
       
   136 					} else {
   127 						modal.destroy();
   137 						modal.destroy();
       
   138 					}
   128 				} else {
   139 				} else {
   129 					modal.destroy();
   140 					modal.destroy();
   130 				}
   141 				}
   131 
   142 
   132 			}));
   143 			}));
   137 		},
   148 		},
   138 
   149 
   139 		getOpenModals: function () {
   150 		getOpenModals: function () {
   140 			var openModals = [];
   151 			var openModals = [];
   141 			for (var i = 0; i < this.stack.length; i++) {
   152 			for (var i = 0; i < this.stack.length; i++) {
   142 				if (this.stack[i].isShown) openModals.push(this.stack[i]);
   153 				if (this.stack[i].isShown) {
       
   154 					openModals.push(this.stack[i]);
       
   155 				}
   143 			}
   156 			}
   144 
   157 
   145 			return openModals;
   158 			return openModals;
   146 		},
   159 		},
   147 
   160 
   151 
   164 
   152 		setFocus: function () {
   165 		setFocus: function () {
   153 			var topModal;
   166 			var topModal;
   154 
   167 
   155 			for (var i = 0; i < this.stack.length; i++) {
   168 			for (var i = 0; i < this.stack.length; i++) {
   156 				if (this.stack[i].isShown) topModal = this.stack[i];
   169 				if (this.stack[i].isShown) {
   157 			}
   170 					topModal = this.stack[i];
   158 
   171 				}
   159 			if (!topModal) return;
   172 			}
       
   173 
       
   174 			if (!topModal) {
       
   175 				return;
       
   176 			}
   160 
   177 
   161 			topModal.focus();
   178 			topModal.focus();
   162 		},
   179 		},
   163 
   180 
   164 		destroyModal: function (modal) {
   181 		destroyModal: function (modal) {
   165 			modal.$element.off('.modalmanager');
   182 			modal.$element.off('.modalmanager');
   166 			if (modal.$backdrop) this.removeBackdrop(modal);
   183 			if (modal.$backdrop) {
       
   184 				this.removeBackdrop(modal);
       
   185 			}
   167 			this.stack.splice(this.getIndexOfModal(modal), 1);
   186 			this.stack.splice(this.getIndexOfModal(modal), 1);
   168 
   187 
   169 			var hasOpenModal = this.hasOpenModal();
   188 			var hasOpenModal = this.hasOpenModal();
   170 
   189 
   171 			this.$element.toggleClass('modal-open', hasOpenModal);
   190 			this.$element.toggleClass('modal-open', hasOpenModal);
   183 			return this.stack[index];
   202 			return this.stack[index];
   184 		},
   203 		},
   185 
   204 
   186 		getIndexOfModal: function (modal) {
   205 		getIndexOfModal: function (modal) {
   187 			for (var i = 0; i < this.stack.length; i++) {
   206 			for (var i = 0; i < this.stack.length; i++) {
   188 				if (modal === this.stack[i]) return i;
   207 				if (modal === this.stack[i]) {
       
   208 					return i;
       
   209 				}
   189 			}
   210 			}
   190 		},
   211 		},
   191 
   212 
   192 		replace: function (callback) {
   213 		replace: function (callback) {
   193 			var topModal;
   214 			var topModal;
   194 
   215 
   195 			for (var i = 0; i < this.stack.length; i++) {
   216 			for (var i = 0; i < this.stack.length; i++) {
   196 				if (this.stack[i].isShown) topModal = this.stack[i];
   217 				if (this.stack[i].isShown) {
       
   218 					topModal = this.stack[i];
       
   219 				}
   197 			}
   220 			}
   198 
   221 
   199 			if (topModal) {
   222 			if (topModal) {
   200 				this.$backdropHandle = topModal.$backdrop;
   223 				this.$backdropHandle = topModal.$backdrop;
   201 				topModal.$backdrop = null;
   224 				topModal.$backdrop = null;
   202 
   225 
   203 				callback && topModal.$element.one('hidden',
   226 				if (callback) {
   204 												  targetIsSelf($.proxy(callback, this)));
   227 					topModal.$element.one('hidden',
       
   228 										  targetIsSelf($.proxy(callback, this)));
       
   229 				}
   205 
   230 
   206 				topModal.hide();
   231 				topModal.hide();
   207 			} else if (callback) {
   232 			} else if (callback) {
   208 				callback();
   233 				callback();
   209 			}
   234 			}
   223 					.appendTo(this.$element);
   248 					.appendTo(this.$element);
   224 			} else {
   249 			} else {
   225 				$backdrop = this.$backdropHandle;
   250 				$backdrop = this.$backdropHandle;
   226 				$backdrop.off('.modalmanager');
   251 				$backdrop.off('.modalmanager');
   227 				this.$backdropHandle = null;
   252 				this.$backdropHandle = null;
   228 				this.isLoading && this.removeSpinner();
   253 				if (this.isLoading) {
       
   254 					this.removeSpinner();
       
   255 				}
   229 			}
   256 			}
   230 
   257 
   231 			return $backdrop;
   258 			return $backdrop;
   232 		},
   259 		},
   233 
   260 
   241 
   268 
   242 			$container = $('<div class="modal-scrollable">')
   269 			$container = $('<div class="modal-scrollable">')
   243 				.css('z-index', getzIndex('modal', this.getOpenModals().length))
   270 				.css('z-index', getzIndex('modal', this.getOpenModals().length))
   244 				.appendTo(this.$element);
   271 				.appendTo(this.$element);
   245 
   272 
   246 			if (modal && modal.options.backdrop != 'static') {
   273 			if (modal && modal.options.backdrop === 'hide') {
   247 				$container.on('click.modal', targetIsSelf(function (e) {
   274 				$container.on('click.modal', targetIsSelf(function (e) {
   248 					modal.hide();
   275 					modal.hide();
   249 				}));
   276 				}));
   250 			} else if (modal) {
   277 			} else if (modal && modal.options.backdrop === 'attention') {
   251 				$container.on('click.modal', targetIsSelf(function (e) {
   278 				$container.on('click.modal', targetIsSelf(function (e) {
   252 					modal.attention();
   279 					modal.attention();
   253 				}));
   280 				}));
   254 			}
   281 			}
   255 
   282 
   267 
   294 
   268 				modal.$backdrop = this.createBackdrop(animate, modal.options.backdropTemplate);
   295 				modal.$backdrop = this.createBackdrop(animate, modal.options.backdropTemplate);
   269 
   296 
   270 				modal.$backdrop.css('z-index', getzIndex('backdrop', this.getOpenModals().length));
   297 				modal.$backdrop.css('z-index', getzIndex('backdrop', this.getOpenModals().length));
   271 
   298 
   272 				if (doAnimate) modal.$backdrop[0].offsetWidth; // force reflow
   299 				if (doAnimate) {
       
   300 					modal.$backdrop[0].offsetWidth;
       
   301 				} // force reflow
   273 
   302 
   274 				modal.$backdrop.addClass('in');
   303 				modal.$backdrop.addClass('in');
   275 
   304 
   276 				this.backdropCount += 1;
   305 				this.backdropCount += 1;
   277 
   306 
   278 				doAnimate ?
   307 				if (doAnimate) {
   279 					modal.$backdrop.one($.support.transition.end, callback) :
   308 					modal.$backdrop.one($.support.transition.end, callback);
       
   309 				} else {
   280 					callback();
   310 					callback();
       
   311 				}
   281 
   312 
   282 			} else if (!modal.isShown && modal.$backdrop) {
   313 			} else if (!modal.isShown && modal.$backdrop) {
   283 				modal.$backdrop.removeClass('in');
   314 				modal.$backdrop.removeClass('in');
   284 
   315 
   285 				this.backdropCount -= 1;
   316 				this.backdropCount -= 1;
   286 
   317 
   287 				var that = this;
   318 				var that = this;
   288 
   319 
   289 				$.support.transition && modal.$element.hasClass('fade') ?
   320 				if ($.support.transition && modal.$element.hasClass('fade')) {
   290 					modal.$backdrop.one($.support.transition.end, function () {
   321 					modal.$backdrop.one($.support.transition.end, function () {
   291 						that.removeBackdrop(modal)
   322 						that.removeBackdrop(modal);
   292 					}) :
   323 					});
       
   324 				} else {
   293 					that.removeBackdrop(modal);
   325 					that.removeBackdrop(modal);
       
   326 				}
   294 
   327 
   295 			} else if (callback) {
   328 			} else if (callback) {
   296 				callback();
   329 				callback();
   297 			}
   330 			}
   298 		},
   331 		},
   299 
   332 
   300 		removeSpinner: function () {
   333 		removeSpinner: function () {
   301 			this.$spinner && this.$spinner.remove();
   334 			if (this.$spinner) {
       
   335 				this.$spinner.remove();
       
   336 			}
   302 			this.$spinner = null;
   337 			this.$spinner = null;
   303 			this.isLoading = false;
   338 			this.isLoading = false;
   304 		},
   339 		},
   305 
   340 
   306 		removeLoading: function () {
   341 		removeLoading: function () {
   307 			this.$backdropHandle && this.$backdropHandle.remove();
   342 			if (this.$backdropHandle) {
       
   343 				this.$backdropHandle.remove();
       
   344 			}
   308 			this.$backdropHandle = null;
   345 			this.$backdropHandle = null;
   309 			this.removeSpinner();
   346 			this.removeSpinner();
   310 		},
   347 		},
   311 
   348 
   312 		loading: function (callback) {
   349 		loading: function (callback) {
   337 					.append($spinner)
   374 					.append($spinner)
   338 					.on('click.modalmanager', $.proxy(this.loading, this));
   375 					.on('click.modalmanager', $.proxy(this.loading, this));
   339 
   376 
   340 				this.isLoading = true;
   377 				this.isLoading = true;
   341 
   378 
   342 				$.support.transition ?
   379 				if ($.support.transition) {
   343 					this.$backdropHandle.one($.support.transition.end, callback) :
   380 					this.$backdropHandle.one($.support.transition.end, callback);
       
   381 				} else {
   344 					callback();
   382 					callback();
       
   383 				}
   345 
   384 
   346 			} else if (this.isLoading && this.$backdropHandle) {
   385 			} else if (this.isLoading && this.$backdropHandle) {
   347 				this.$backdropHandle.removeClass('in');
   386 				this.$backdropHandle.removeClass('in');
   348 
   387 
   349 				var that = this;
   388 				var that = this;
   350 				$.support.transition ?
   389 				if ($.support.transition) {
   351 					this.$backdropHandle.one($.support.transition.end, function () {
   390 					this.$backdropHandle.one($.support.transition.end, function () {
   352 						that.removeLoading()
   391 						that.removeLoading();
   353 					}) :
   392 					});
       
   393 				} else {
   354 					that.removeLoading();
   394 					that.removeLoading();
       
   395 				}
   355 
   396 
   356 			} else if (callback) {
   397 			} else if (callback) {
   357 				callback(this.isLoading);
   398 				callback(this.isLoading);
   358 			}
   399 			}
   359 		}
   400 		}
   371 
   412 
   372 			if (typeof zIndexFactor === 'undefined') {
   413 			if (typeof zIndexFactor === 'undefined') {
   373 				var $baseModal = $('<div class="modal hide" />').appendTo('body'),
   414 				var $baseModal = $('<div class="modal hide" />').appendTo('body'),
   374 					$baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
   415 					$baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
   375 
   416 
   376 				baseIndex['modal'] = +$baseModal.css('z-index');
   417 				baseIndex.modal = +$baseModal.css('z-index');
   377 				baseIndex['backdrop'] = +$baseBackdrop.css('z-index');
   418 				baseIndex.backdrop = +$baseBackdrop.css('z-index');
   378 				zIndexFactor = baseIndex['modal'] - baseIndex['backdrop'];
   419 				zIndexFactor = baseIndex.modal - baseIndex.backdrop;
   379 
   420 
   380 				$baseModal.remove();
   421 				$baseModal.remove();
   381 				$baseBackdrop.remove();
   422 				$baseBackdrop.remove();
   382 				$baseBackdrop = $baseModal = null;
   423 				$baseBackdrop = $baseModal = null;
   383 			}
   424 			}
   384 
   425 
   385 			return baseIndex[type] + (zIndexFactor * pos);
   426 			return baseIndex[type] + (zIndexFactor * pos);
   386 
   427 
   387 		}
   428 		};
   388 	}());
   429 	}());
   389 
   430 
   390 	// make sure the event target is the modal itself in order to prevent
   431 	// make sure the event target is the modal itself in order to prevent
   391 	// other components such as tabsfrom triggering the modal manager.
   432 	// other components such as tabsfrom triggering the modal manager.
   392 	// if Boostsrap namespaced events, this would not be needed.
   433 	// if Boostsrap namespaced events, this would not be needed.
   405 	$.fn.modalmanager = function (option, args) {
   446 	$.fn.modalmanager = function (option, args) {
   406 		return this.each(function () {
   447 		return this.each(function () {
   407 			var $this = $(this),
   448 			var $this = $(this),
   408 				data = $this.data('modalmanager');
   449 				data = $this.data('modalmanager');
   409 
   450 
   410 			if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)));
   451 			if (!data) {
   411 			if (typeof option === 'string') data[option].apply(data, [].concat(args))
   452 				$this.data('modalmanager', (data = new ModalManager(this, option)));
   412 		})
   453 			}
       
   454 			if (typeof option === 'string') {
       
   455 				data[option].apply(data, [].concat(args));
       
   456 			}
       
   457 		});
   413 	};
   458 	};
   414 
   459 
   415 	$.fn.modalmanager.defaults = {
   460 	$.fn.modalmanager.defaults = {
   416 		backdropLimit: 999,
   461 		backdropLimit: 999,
   417 		resize: true,
   462 		resize: true,
   418 		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>',
   463 		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>',
   419 		backdropTemplate: '<div class="modal-backdrop" />'
   464 		backdropTemplate: '<div class="modal-backdrop" />'
   420 	};
   465 	};
   421 
   466 
   422 	$.fn.modalmanager.Constructor = ModalManager
   467 	$.fn.modalmanager.Constructor = ModalManager;
   423 
   468 
   424 	// ModalManager handles the modal-open class so we need 
   469 	// ModalManager handles the modal-open class so we need 
   425 	// to remove conflicting bootstrap 3 event handlers
   470 	// to remove conflicting bootstrap 3 event handlers
   426 	$(function () {
   471 	$(function () {
   427 		$(document).off('show.bs.modal').off('hidden.bs.modal');
   472 		$(document).off('show.bs.modal').off('hidden.bs.modal');