src/myams/resources/js/myams-dialog.js
changeset 0 f05d7aea098a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/myams/resources/js/myams-dialog.js	Fri Jul 10 16:59:11 2020 +0200
@@ -0,0 +1,300 @@
+/**
+ * MyAMS modal dialogs management
+ */
+(function($, globals) {
+
+	var ams = globals.MyAMS;
+
+	ams.dialog = {
+
+		/**
+		 * List of registered 'shown' callbacks
+		 */
+		_shown_callbacks: [],
+
+		/**
+		 * Register a callback which should be called when a dialog is shown
+		 */
+		registerShownCallback: function(callback, element) {
+			var dialog;
+			if (element) {
+				dialog = element.objectOrParentWithClass('modal-dialog');
+			}
+
+			var callbacks;
+			if (dialog && dialog.exists()) {
+				callbacks = dialog.data('shown-callbacks');
+				if (callbacks === undefined) {
+					callbacks = [];
+					dialog.data('shown-callbacks', callbacks);
+				}
+			} else {
+				callbacks = ams.dialog._shown_callbacks;
+			}
+			if (callbacks.indexOf(callback) < 0) {
+				callbacks.push(callback);
+			}
+		},
+
+		/**
+		 * List of registered 'hide' callbacks
+		 */
+		_hide_callbacks: [],
+
+		/**
+		 * Register a callback which should be called when a dialog is closed
+		 */
+		registerHideCallback: function(callback, element) {
+			var dialog;
+			if (element) {
+				dialog = element.objectOrParentWithClass('modal-dialog');
+			}
+
+			var callbacks;
+			if (dialog && dialog.exists()) {
+				callbacks = dialog.data('hide-callbacks');
+				if (callbacks === undefined) {
+					callbacks = [];
+					dialog.data('hide-callbacks', callbacks);
+				}
+			} else {
+				callbacks = ams.dialog._hide_callbacks;
+			}
+			if (callbacks.indexOf(callback) < 0) {
+				callbacks.push(callback);
+			}
+		},
+
+		/**
+		 * Modal dialog opener
+		 */
+		open: function(source, options, callbacks) {
+			ams.ajax && ams.ajax.check($.fn.modalmanager,
+									   ams.baseURL + 'ext/bootstrap-modalmanager' + ams.devext + '.js',
+									   function() {
+										   ams.ajax.check($.fn.modal.defaults,
+														  ams.baseURL + 'ext/bootstrap-modal' + ams.devext + '.js',
+														  function(first_load) {
+															  if (first_load) {
+																  $(document).off('click.modal');
+																  $.fn.modal.defaults.spinner = $.fn.modalmanager.defaults.spinner =
+																	  '<div class="loading-spinner" style="width: 200px; margin-left: -100px;">' +
+																	  '<div class="progress progress-striped active">' +
+																	  '<div class="progress-bar" style="width: 100%;"></div>' +
+																	  '</div>' +
+																	  '</div>';
+															  }
+
+															  var sourceData;
+															  var url;
+															  if (typeof (source) === 'string') {
+																  sourceData = {};
+																  url = source;
+															  } else {
+																  sourceData = source.data();
+																  url = source.attr('href') || sourceData.amsUrl;
+																  var url_getter = ams.getFunctionByName(url);
+																  if (typeof (url_getter) === 'function') {
+																	  url = url_getter.call(source);
+																  }
+															  }
+															  if (!url) {
+																  return;
+															  }
+															  $('body').modalmanager('loading');
+															  if (url.indexOf('#') === 0) {
+																  // Inner hidden modal dialog
+																  $(url).modal('show');
+															  } else {
+																  // Remote URL modal dialog
+																  $.ajax({
+																			 url: url,
+																			 type: 'get',
+																			 cache: sourceData.amsAllowCache === undefined ? false : sourceData.amsAllowCache,
+																			 data: options,
+																			 success: function(data, status, request) {
+																				 $('body').modalmanager('removeLoading');
+																				 var response = ams.ajax.getResponse(request);
+																				 var dataType = response.contentType;
+																				 var result = response.data;
+																				 switch (dataType) {
+																					 case 'json':
+																						 ams.ajax.handleJSON(result, $($(source).data('ams-json-target') || '#content'));
+																						 break;
+																					 case 'script':
+																						 break;
+																					 case 'xml':
+																						 break;
+																					 case 'html':
+																					 /* falls through */
+																					 case 'text':
+																					 /* falls through */
+																					 default:
+																						 var content = $(result);
+																						 var dialog = $('.modal-dialog', content.wrap('<div></div>').parent());
+																						 var dialogData = dialog.data() || {};
+																						 var dataOptions = {
+																							 backdrop: 'static',
+																							 overflow: dialogData.amsModalOverflow || '.modal-viewport',
+																							 maxHeight: dialogData.amsModalMaxHeight === undefined ?
+																								 function() {
+																							 		 var win_height = $(window).height(),
+																										 top_margin = parseInt(dialog.css('margin-top')),
+																									 	 top_padding = Math.round(win_height / 10);
+																									 return win_height -
+																										 $('.modal-header', content).outerHeight(true) -
+																										 $('footer', content).outerHeight(true) - top_margin - top_padding;
+																								 }
+																								 : ams.getFunctionByName(dialogData.amsModalMaxHeight)
+																						 };
+																						 var settings = $.extend({}, dataOptions, dialogData.amsModalOptions);
+																						 settings = ams.executeFunctionByName(dialogData.amsModalInitCallback, dialog, settings) || settings;
+																						 if (callbacks) {
+																							 if (callbacks.shown) {
+																								 ams.dialog.registerShownCallback(callbacks.shown, content);
+																							 }
+																							 if (callbacks.hide) {
+																								 ams.dialog.registerHideCallback(callbacks.hide, content);
+																							 }
+																						 }
+																						 $('<div>').addClass('modal fade')
+																							 .append(content)
+																							 .modal(settings)
+																							 .on('shown', ams.dialog.shown)
+																							 .on('hidden', ams.dialog.hidden);
+																						 ams.initContent && ams.initContent(content);
+																						 if (sourceData.amsLogEvent !== false) {
+																							 ams.stats && ams.stats.logPageview(url);
+																						 }
+																				 }
+																			 }
+																		 });
+															  }
+														  });
+									   });
+		},
+
+		/**
+		 * Modals shown callback
+		 * This callback is used to initialize modal's viewport size
+		 */
+		shown: function(e) {
+
+			function resetViewport(ev) {
+				var top = $('.scrollmarker.top', viewport),
+					topPosition = viewport.scrollTop();
+				if (topPosition > 0) {
+					top.show();
+				} else {
+					top.hide();
+				}
+				var bottom = $('.scrollmarker.bottom', viewport);
+				if (maxHeight + topPosition >= viewport.get(0).scrollHeight) {
+					bottom.hide();
+				} else {
+					bottom.show();
+				}
+			}
+
+			var modal = e.target,
+				viewport = $('.modal-viewport', modal);
+			if (viewport.exists()) {
+				var maxHeight = parseInt(viewport.css('max-height')),
+					barWidth = $.scrollbarWidth();
+				if ((viewport.css('overflow') !== 'hidden') &&
+					(viewport.height() === maxHeight)) {
+					$('<div></div>').addClass('scrollmarker')
+						.addClass('top')
+						.css('top', 0)
+						.css('width', viewport.width() - barWidth)
+						.hide()
+						.appendTo(viewport);
+					$('<div></div>').addClass('scrollmarker')
+						.addClass('bottom')
+						.css('top', maxHeight - 20)
+						.css('width', viewport.width() - barWidth)
+						.appendTo(viewport);
+					viewport.scroll(resetViewport);
+					viewport.off('resize')
+						.on('resize', resetViewport);
+				} else {
+					$('.scrollmarker', viewport).remove();
+				}
+			}
+
+			// Check for shown callbacks defined via data API
+			$('[data-ams-shown-callback]', modal).each(function() {
+				var callback = ams.getFunctionByName($(this).data('ams-shown-callback'));
+				if (callback) {
+					callback.call(modal, this);
+				}
+			});
+			// Call shown callbacks registered for this dialog
+			var index,
+				callbacks = $('.modal-dialog', modal).data('shown-callbacks');
+			if (callbacks) {
+				for (index=0; index < callbacks.length; index++) {
+					callbacks[index].call(modal);
+				}
+			}
+			// Call globally registered shown callbacks
+			callbacks = ams.dialog._shown_callbacks;
+			if (callbacks) {
+				for (index=0; index < callbacks.length; index++) {
+					callbacks[index].call(modal);
+				}
+			}
+
+			ams.form && ams.form.setFocus(modal);
+		},
+
+		/**
+		 * Close modal dialog associated with given context
+		 */
+		close: function(context) {
+			if (typeof(context) === 'string') {
+				context = $(context);
+			}
+			var modal = context.parents('.modal').data('modal');
+			if (modal) {
+				var manager = $('body').data('modalmanager');
+				if (manager && (manager.getOpenModals().indexOf(modal) >= 0)) {
+					modal.hide();
+				}
+			}
+		},
+
+		/**
+		 * Modals hidden callback
+		 * This callback can be used to clean contents added by plug-ins
+		 */
+		hidden: function(e) {
+			var modal = e.target;
+			// Call registered cleaning callbacks
+			ams.skin && ams.skin.cleanContainer(modal);
+			// Check for hidden callbacks defined via data API
+			$('[data-ams-hidden-callback]', modal).each(function() {
+				var callback = ams.getFunctionByName($(this).data('ams-hidden-callback'));
+				if (callback) {
+					callback.call(modal, this);
+				}
+			});
+			// Call hidden callbacks registered for this dialog
+			var index;
+			var callbacks = $('.modal-dialog', modal).data('hide-callbacks');
+			if (callbacks) {
+				for (index=0; index < callbacks.length; index++) {
+					callbacks[index].call(modal);
+				}
+			}
+			// Call globally registered hidden callbacks
+			callbacks = ams.dialog._hide_callbacks;
+			if (callbacks) {
+				for (index=0; index < callbacks.length; index++) {
+					callbacks[index].call(modal);
+				}
+			}
+		}
+	};
+
+})(jQuery, this);