src/pyams_skin/resources/js/myams.js
changeset 64 3fe1d315747c
parent 57 fc253f455a90
child 69 a361355b55c7
--- a/src/pyams_skin/resources/js/myams.js	Wed May 20 12:34:50 2015 +0200
+++ b/src/pyams_skin/resources/js/myams.js	Wed May 20 12:36:02 2015 +0200
@@ -110,6 +110,17 @@
 		},
 
 		/*
+		 * Build an array of attributes of the given selection
+		 */
+		listattr: function(attr) {
+			var result = [];
+			this.each(function() {
+				result.push($(this).attr(attr));
+			});
+			return result;
+		},
+
+		/*
 		 * CSS style function
 		 * Code from Aram Kocharyan on stackoverflow.com
 		 */
@@ -153,6 +164,57 @@
 		},
 
 		/*
+		 * Context menu handler
+		 */
+		contextMenu: function(settings) {
+
+			function getMenuPosition(mouse, direction, scrollDir) {
+				var win = $(window)[direction](),
+					menu = $(settings.menuSelector)[direction](),
+					position = mouse;
+				// opening menu would pass the side of the page
+				if (mouse + menu > win && menu < mouse)
+					position -= menu;
+				return position;
+			}
+
+			return this.each(function () {
+
+				// Open context menu
+				$('a', $(settings.menuSelector)).each(function() {
+					$(this).data('ams-context-menu', true);
+				});
+				$(this).on("contextmenu", function (e) {
+					// return native menu if pressing control
+					if (e.ctrlKey)
+						return;
+					//open menu
+					$(settings.menuSelector).data("invokedOn", $(e.target))
+											.show()
+											.css({
+												position: 'fixed',
+												left: getMenuPosition(e.clientX, 'width', 'scrollLeft') - 10,
+												top: getMenuPosition(e.clientY, 'height', 'scrollTop') - 10
+											})
+											.off('click')
+											.on('click', function (e) {
+												$(this).hide();
+												var $invokedOn = $(this).data("invokedOn");
+												var $selectedMenu = $(e.target);
+												settings.menuSelected.call(this, $invokedOn, $selectedMenu);
+												ams.event.stop(e);
+											});
+					return false;
+				});
+
+				//make sure menu closes on any click
+				$(document).click(function () {
+					$(settings.menuSelector).hide();
+				});
+			});
+		},
+
+		/*
 		 * Main menus manager
 		 */
 		myams_menu: function(options) {
@@ -199,54 +261,49 @@
 			menu.find("LI A").on('click', function() {
 				var link = $(this);
 				var parent_ul = link.parent().find("UL");
-				if (parent_ul.size() != 0) {
-					if (settings.accordion) {
-						// Do nothing when the list is open
-						if (!parent_ul.is(':visible')) {
-							var parents = link.parent().parents("UL");
-							var visible = menu.find("UL:visible");
-							visible.each(function(visibleIndex) {
-								var close = true;
-								parents.each(function(parentIndex) {
-									if (parents[parentIndex] == visible[visibleIndex]) {
-										close = false;
-										return false;
-									}
+				if (settings.accordion) {
+					var parents = link.parent().parents("UL");
+					var visible = menu.find("UL:visible");
+					visible.each(function(visibleIndex) {
+						var close = true;
+						parents.each(function(parentIndex) {
+							if (parents[parentIndex] == visible[visibleIndex]) {
+								close = false;
+								return false;
+							}
+						});
+						if (close) {
+							if (parent_ul != visible[visibleIndex]) {
+								$(visible[visibleIndex]).slideUp(settings.speed, function() {
+									link.parent("LI")
+										.find("b:first")
+										.html(settings.closedSign);
+									link.parent("LI")
+										.removeClass("open");
 								});
-								if (close) {
-									if (parent_ul != visible[visibleIndex]) {
-										$(visible[visibleIndex]).slideUp(settings.speed, function() {
-											link.parent("LI")
-												.find("b:first")
-												.html(settings.closedSign);
-											link.parent("LI")
-												.removeClass("open");
-										});
-									}
-								}
-							});
+							}
 						}
-					}
-					var first_ul = link.parent().find("UL:first");
-					if (!link.attr('href').replace(/^#/,'') &&
-						first_ul.is(":visible") &&
-						!first_ul.hasClass("active")) {
-						first_ul.slideUp(settings.speed, function() {
-							link.parent("LI")
-								.removeClass("open")
-								.find("B:first")
-								.delay(settings.speed)
-								.html(settings.closedSign);
-						});
-					} else /*if (link.attr('href') != location.hash)*/ {
-						first_ul.slideDown(settings.speed, function() {
-							link.parent("LI")
-								.addClass("open")
-								.find("B:first")
-								.delay(settings.speed)
-								.html(settings.openedSign);
-						});
-					}
+					});
+				}
+				var first_ul = link.parent().find("UL:first");
+				if (!link.attr('href').replace(/^#/,'') &&
+					first_ul.is(":visible") &&
+					!first_ul.hasClass("active")) {
+					first_ul.slideUp(settings.speed, function() {
+						link.parent("LI")
+							.removeClass("open")
+							.find("B:first")
+							.delay(settings.speed)
+							.html(settings.closedSign);
+					});
+				} else /*if (link.attr('href') != location.hash)*/ {
+					first_ul.slideDown(settings.speed, function() {
+						link.parent("LI")
+							.addClass("open")
+							.find("B:first")
+							.delay(settings.speed)
+							.html(settings.openedSign);
+					});
 				}
 			});
 		}
@@ -323,6 +380,7 @@
 	if (window.MyAMS === undefined) {
 		window.MyAMS = {
 			devmode: true,
+			devext: '',
 			lang: 'en',
 			throttle_delay: 350,
 			menu_speed: 235,
@@ -345,6 +403,7 @@
 		var script = $('script[src$="/myams.js"], script[src$="/myams.min.js"]');
 		var src = script.attr("src");
 		ams.devmode = !src.endsWith('.min.js');
+		ams.devext = ams.devmode ? '' : '.min';
 		return src.substring(0, src.lastIndexOf('/') + 1);
 	})();
 
@@ -628,6 +687,20 @@
 		},
 
 		/**
+		 * AJAX start callback
+		 */
+		start: function() {
+			$('#ajax-gear').show();
+		},
+
+		/**
+		 * AJAX stop callback
+		 */
+		stop: function() {
+			$('#ajax-gear').hide();
+		},
+
+		/**
 		 * Handle AJAX upload and download progress
 		 *
 		 * @param event: the source event
@@ -668,7 +741,7 @@
 				type: 'post',
 				cache: false,
 				async: typeof(callback) == 'function',
-				data: $.param(data, true),
+				data: $.param(data),
 				dataType: 'json',
 				success: callback || function(data /*, status*/) {
 					result = data.result;
@@ -1781,7 +1854,7 @@
 			var source = $(this);
 			var label = source.parents('label');
 			var target = source.data('ams-select2-target');
-			$('INPUT[name="' + target + '"]', label).data('select2').val('');
+			$('[name="' + target + '"]', label).data('select2').val('');
 		},
 
 		/** Select2 selection formatter */
@@ -1855,6 +1928,52 @@
 			}
 		},
 
+		/** Context menu handler */
+		contextMenuHandler: function(target, menu) {
+			var menu_data = menu.data();
+			if (menu_data.toggle == 'modal') {
+				ams.dialog.open(menu);
+			} else {
+				var href = menu.attr('href') || menu_data.amsUrl;
+				if (!href || href.startsWith('javascript:') || menu.attr('target'))
+					return;
+				ams.event.stop();
+				var href_getter = ams.getFunctionByName(href);
+				if (typeof(href_getter) == 'function') {
+					href = href_getter.call(menu, target);
+				}
+				if (typeof(href) == 'function') {
+					// Javascript function call
+					href.call(menu, target);
+				} else {
+					// Standard AJAX or browser URL call
+					// Convert %23 chars to #
+					href = href.replace(/\%23/, '#');
+					var target = menu.data('ams-target');
+					if (target) {
+						ams.form.confirmChangedForm(target, function () {
+							ams.skin.loadURL(href, target, menu.data('ams-link-options'), menu.data('ams-link-callback'));
+						});
+					} else {
+						ams.form.confirmChangedForm(function () {
+							if (href.startsWith('#')) {
+								if (href != location.hash) {
+									if (ams.root.hasClass('mobile-view-activated')) {
+										ams.root.removeClass('hidden-menu');
+										window.setTimeout(function () {
+											window.location.hash = href;
+										}, 150);
+									} else
+										window.location.hash = href;
+								}
+							} else
+								window.location = href;
+						});
+					}
+				}
+			}
+		},
+
 		/** Datetimepicker dialog cleaner callback */
 		datetimepickerDialogHiddenCallback: function() {
 			$('.datepicker, .timepicker, .datetimepicker', this).datetimepicker('destroy');
@@ -2222,6 +2341,105 @@
 			},
 
 			/**
+			 * Draggable plug-in
+			 */
+			draggable: function(element) {
+				var draggables = $('.draggable', element);
+				if (draggables.length > 0) {
+					draggables.each(function() {
+						var draggable = $(this);
+						var data = draggable.data();
+						var data_options = {
+							containment: data.amsDraggableContainment,
+							helper: ams.getFunctionByName(data.amsDraggableHelper) || data.amsDraggableHelper,
+							start: ams.getFunctionByName(data.amsDraggableStart),
+							stop: ams.getFunctionByName(data.amsDraggableStop)
+						};
+						var settings = $.extend({}, data_options, data.amsDraggableOptions);
+						settings = ams.executeFunctionByName(data.amsDraggableInitCallback, draggable, settings) || settings;
+						var plugin = draggable.draggable(settings);
+						draggable.disableSelection();
+						ams.executeFunctionByName(data.amsDraggableAfterInitCallback, draggable, plugin, settings);
+					});
+				}
+			},
+
+			/**
+			 * Sortable plug-in
+			 */
+			sortable: function(element) {
+				var sortables = $('.sortable', element);
+				if (sortables.length > 0) {
+					sortables.each(function() {
+						var sortable = $(this);
+						var data = sortable.data();
+						var data_options = {
+							items: data.amsSortableItems,
+							handle: data.amsSortableHandle,
+							connectWith: data.amsSortableConnectwith,
+							start: ams.getFunctionByName(data.amsSortableStart),
+							over: ams.getFunctionByName(data.amsSortableOver),
+							containment: data.amsSortableContainment,
+							placeholder: data.amsSortablePlaceholder,
+							stop: ams.getFunctionByName(data.amsSortableStop)
+						};
+						var settings = $.extend({}, data_options, data.amsSortableOptions);
+						settings = ams.executeFunctionByName(data.amsSortableInitCallback, sortable, settings) || settings;
+						var plugin = sortable.sortable(settings);
+						sortable.disableSelection();
+						ams.executeFunctionByName(data.amsSortableAfterInitCallback, sortable, plugin, settings);
+					});
+				}
+			},
+
+			/**
+			 * Resizable plug-in
+			 */
+			resizable: function(element) {
+				var resizables = $('.resizable', element);
+				if (resizables.length > 0) {
+					resizables.each(function() {
+						var resizable = $(this);
+						var data = resizable.data();
+						var data_options = {
+							autoHide: data.amsResizableAutohide === false ? true : data.amsResizableAutohide,
+							containment: data.amsResizableContainment,
+							grid: data.amsResizableGrid,
+							handles: data.amsResizableHandles,
+							start: ams.getFunctionByName(data.amsResizableStart),
+							stop: ams.getFunctionByName(data.amsResizableStop)
+						};
+						var settings = $.extend({}, data_options, data.amsResizableOptions);
+						settings = ams.executeFunctionByName(data.amsResizableInitCallback, resizable, settings) || settings;
+						var plugin = resizable.resizable(settings);
+						resizable.disableSelection();
+						ams.executeFunctionByName(data.amsResizableAfterInitCallback, resizable, plugin, settings);
+					});
+				}
+			},
+
+			/**
+			 * Context menu plug-in
+			 */
+			contextMenu: function(element) {
+				var menus = $('.context-menu', element);
+				if (menus.length > 0) {
+					menus.each(function() {
+						var menu = $(this);
+						var data = menu.data();
+						var data_options = {
+							menuSelector: data.amsContextmenuSelector,
+							menuSelected: ams.helpers.contextMenuHandler
+						};
+						var settings = $.extend({}, data_options, data.amsContextmenuOptions);
+						settings = ams.executeFunctionByName(data.amsContextmenuInitCallback, menu, settings) || settings;
+						var plugin = menu.contextMenu(settings);
+						ams.executeFunctionByName(data.amsContextmenuAfterInitCallback, menu, plugin, settings);
+					});
+				}
+			},
+
+			/**
 			 * Select2 plug-in
 			 */
 			select2: function(element) {
@@ -2392,15 +2610,14 @@
 											var plugin = select.select2(settings);
 											ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings);
 											if (select.hasClass('ordered')) {
-												$(plugin.context).parents('.select2-parent').find('ul.select2-choices').sortable({
-													containment: 'parent',
-													start: function() {
-														select.select2('onSortStart');
-													},
-													update: function() {
-														select.select2('onSortEnd');
-													}
-											   })
+												select.addClass('nofloat');
+												ams.ajax.check($.fn.select2Sortable,
+															   ams.baseURL + 'ext/jquery-select2-sortable' + (ams.devmode ? '.js' : '.min.js'),
+															   function() {
+																	select.select2Sortable({
+																		bindOrder: 'sortableStop'
+																	});
+															   });
 											}
 
 											select.on('change', function() {
@@ -3608,10 +3825,14 @@
 								$('.alert', container.parents('.alerts-container')).remove();
 								container.css({opacity: '0.0'})
 										 .html(data)
+										 .removeClass('hidden')
 										 .delay(50)
 										 .animate({opacity: '1.0'}, 300);
 								ams.initContent(container);
 						}
+						if (options && options.afterLoadCallback) {
+							ams.executeFunctionByName(options.afterLoadCallback, this);
+						}
 					}
 				},
 				error: function(request, options, error) {
@@ -3686,6 +3907,8 @@
 				return request;
 			}
 		});
+		$(document).ajaxStart(ams.ajax.start);
+		$(document).ajaxStop(ams.ajax.stop);
 		$(document).ajaxError(ams.error.ajax);
 
 		// Check mobile/desktop
@@ -3848,16 +4071,16 @@
 			$(document).on('click', 'a[href!="#"]:not([data-toggle]), [data-ams-url]:not([data-toggle])', function(e) {
 				var link = $(e.currentTarget);
 				var href = link.attr('href') || link.data('ams-url');
-				if (!href || href.startsWith('javascript:') || link.attr('target'))
+				if (!href || href.startsWith('javascript:') || link.attr('target') || (link.data('ams-context-menu') === true))
 					return;
 				e.preventDefault();
+				e.stopPropagation();
 				var href_getter = ams.getFunctionByName(href);
 				if (typeof(href_getter) == 'function') {
 					href = href_getter.call(link);
 				}
 				if (typeof(href) == 'function') {
 					// Javascript function call
-					e.stopPropagation();
 					href.call(link);
 				} else {
 					// Standard AJAX or browser URL call
@@ -3906,6 +4129,8 @@
 		$(document).off('click.modal')
 				   .on('click', '[data-toggle="modal"]', function(e) {
 			var source = $(this);
+			if (source.data('ams-context-menu') === true)
+				return;
 			if (source.data('ams-stop-propagation') === true)
 				e.stopPropagation();
 			e.preventDefault();