src/pyams_skin/resources/js/myams.js
changeset 199 2cef7c7c1894
parent 184 c9495342d92c
child 208 d3d38d0b3d18
--- a/src/pyams_skin/resources/js/myams.js	Mon Sep 11 12:31:44 2017 +0200
+++ b/src/pyams_skin/resources/js/myams.js	Mon Sep 11 12:39:16 2017 +0200
@@ -14,6 +14,8 @@
 
 	"use strict";
 
+	var console = globals.console;
+
 	/**
 	 * String prototype extensions
 	 */
@@ -444,8 +446,8 @@
 	 * Basic logging function which log all arguments to console
 	 */
 	MyAMS.log = function() {
-		if (globals.console) {
-			globals.console.log(this, arguments);
+		if (console) {
+			console.log && console.log(this, arguments);
 		}
 	};
 
@@ -688,14 +690,53 @@
 			return msg;
 		},
 
-		copyToClipboard: function() {
-			return function() {
-				var source = $(this);
-				source.parents('.btn-group').removeClass('open');
-				if (globals.prompt) {
-					globals.prompt(MyAMS.i18n.CLIPBOARD_COPY, source.text());
+
+		copyToClipboard: function(text) {
+
+			function doCopy(text) {
+				var copied = false;
+				if (window.clipboardData && window.clipboardData.setData) {
+					// IE specific code
+					copied = clipboardData.setData("Text", text);
+				} else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
+					var textarea = $("<textarea>");
+					textarea.val(text);
+					textarea.css('position', 'fixed');  // Prevent scrolling to bottom of page in MS Edge.
+					textarea.appendTo($('body'));
+					textarea.get(0).select();
+					try {
+						document.execCommand("copy");  // Security exception may be thrown by some browsers.
+						copied = true;
+					} catch (ex) {
+						if (console) {
+							console.warn && console.warn("Copy to clipboard failed.", ex);
+						}
+					} finally {
+						textarea.remove();
+					}
 				}
-			};
+				if (copied) {
+					ams.skin.smallBox('success',
+									  {
+										  title: ams.i18n.CLIPBOARD_COPY_OK,
+										  icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
+										  timeout: 1000
+									  });
+				} else if (globals.prompt) {
+					globals.prompt(MyAMS.i18n.CLIPBOARD_COPY, text);
+				}
+			}
+
+			if (text === undefined) {
+				return function() {
+					var source = $(this);
+					var text = source.text();
+					source.parents('.btn-group').removeClass('open');
+					doCopy(text);
+				};
+			} else {
+				doCopy(text);
+			}
 		}
 	};
 
@@ -709,6 +750,10 @@
 		 * Default JQuery AJAX error handler
 		 */
 		ajax: function(event, response, request, error) {
+			/* user shouldn't be notified of aborted requests */
+			if (error === 'abort') {
+				return;
+			}
 			if (response && response.statusText && response.statusText.toUpperCase() === 'OK') {
 				return;
 			}
@@ -725,9 +770,9 @@
 					timeout: 10000
 				});
 			}
-			if (globals.console) {
-				globals.console.error(event);
-				globals.console.debug(response);
+			if (console) {
+				console.error && console.error(event);
+				console.debug && console.debug(response);
 			}
 		},
 
@@ -749,9 +794,9 @@
 					timeout: 10000
 				});
 			}
-			if (globals.console) {
-				globals.console.error(error);
-				globals.console.debug(request);
+			if (console) {
+				console.error && console.error(error);
+				console.debug && console.debug(request);
 			}
 		}
 	};
@@ -858,8 +903,8 @@
 			if (event.loaded >= event.total) {
 				return;
 			}
-			if (globals.console) {
-				globals.console.log(parseInt((event.loaded / event.total * 100), 10) + "%");
+			if (console) {
+				console.log && console.log(parseInt((event.loaded / event.total * 100), 10) + "%");
 			}
 		},
 
@@ -1032,8 +1077,8 @@
 					}
 					break;
 				default:
-					if (globals.console) {
-						globals.console.log("Unhandled status: " + status);
+					if (console) {
+						console.log && console.log("Unhandled status: " + status);
 					}
 			}
 
@@ -1123,6 +1168,17 @@
 			if (result.event) {
 				form.trigger(result.event, result.event_options);
 			}
+			if (result.events) {
+				var event;
+				for (index  =0; index < result.events.length; index++) {
+					event = result.events[index];
+					if (typeof(event) === 'string') {
+						form.trigger(event, result.events_options);
+					} else {
+						form.trigger(event.event, event.options);
+					}
+				}
+			}
 			if (result.callback) {
 				ams.executeFunctionByName(result.callback, form, result.options);
 			}
@@ -1130,7 +1186,11 @@
 				var callback;
 				for (index=0; index < result.callbacks.length; index++) {
 					callback = result.callbacks[index];
-					ams.executeFunctionByName(callback, form, callback.options);
+					if (typeof(callback) === 'function') {
+						ams.executeFunctionByName(callback, form, callback.options);
+					} else {
+						ams.executeFunctionByName(callback.callback, form, callback.options);
+					}
 				}
 			}
 		}
@@ -1330,6 +1390,16 @@
 		 * @param element: the parent element
 		 */
 		init: function(element) {
+
+			// Store value of hidden inputs
+			$('FORM', element).each(function() {
+				var form = $(this);
+				$('INPUT.select2[type="hidden"]', form).each(function() {
+					var input = $(this);
+					input.data('ams-select2-input-value', input.val());
+				});
+			});
+
 			// Activate form changes if required
 			var forms;
 			if (ams.warnOnFormChange) {
@@ -2706,8 +2776,8 @@
 			}
 			name = name || plugin.name;
 			if (ams.plugins.enabled.indexOf(name) >= 0) {
-				if (globals.console) {
-					globals.console.warn("Plugin " + name + " is already registered!");
+				if (console) {
+					console.warn && console.warn("Plugin " + name + " is already registered!");
 				}
 				return;
 			}
@@ -2775,9 +2845,11 @@
 											   html: data.amsHintHtml,
 											   title: ams.getFunctionByName(data.amsHintTitleGetter) || function () {
 												   var hint = $(this);
-												   return hint.attr('original-title') ||
-														   hint.attr(data.amsHintTitleAttr || 'title') ||
-														   (data.amsHintHtml ? hint.html() : hint.text());
+												   var result = hint.attr('original-title') ||
+																hint.attr(data.amsHintTitleAttr || 'title') ||
+																(data.amsHintHtml ? hint.html() : hint.text());
+												   result = result.replace(/\?_="/, '?_=' + new Date().getTime() + '"');
+												   return result;
 											   },
 											   opacity: data.amsHintOpacity || 0.95,
 											   gravity: data.amsHintGravity || 'sw',
@@ -3354,7 +3426,9 @@
 												format: data.amsDatetimepickerFormat || 'd/m/y',
 												datepicker: true,
 												dayOfWeekStart: 1,
-												timepicker: false
+												timepicker: false,
+												closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+												weeks: data.amsDatetimepickerWeeks
 											};
 											var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
@@ -3386,7 +3460,10 @@
 												format: data.amsDatetimepickerFormat || 'd/m/y H:i',
 												datepicker: true,
 												dayOfWeekStart: 1,
-												timepicker: true
+												timepicker: true,
+												closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+												closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+												weeks: data.amsDatetimepickerWeeks
 											};
 											var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
@@ -3417,7 +3494,8 @@
 												lang: data.amsDatetimepickerLang || ams.lang,
 												format: data.amsDatetimepickerFormat || 'H:i',
 												datepicker: false,
-												timepicker: true
+												timepicker: true,
+												closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect
 											};
 											var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
@@ -3805,48 +3883,6 @@
 			},
 
 			/**
-			 * Wizard plug-in
-			 */
-			wizard: function(element) {
-				var wizards = $('.wizard', element);
-				if (wizards.length > 0) {
-					ams.ajax.check($,
-								   ams.baseURL + 'ext/bootstrap-wizard-1.4.2' + ams.devext + '.js',
-								   function(first_load) {
-										wizards.each(function() {
-											var wizard = $(this);
-											var data = wizard.data();
-											var dataOptions = {
-												withVisible: data.amsWizardWithVisible === undefined ? true : data.amsWizardWithVisible,
-												tabClass: data.amsWizardTabClass,
-												firstSelector: data.amsWizardFirstSelector,
-												previousSelector: data.amsWizardPreviousSelector,
-												nextSelector: data.amsWizardNextSelector,
-												lastSelector: data.amsWizardLastSelector,
-												finishSelector: data.amsWizardFinishSelector,
-												backSelector: data.amsWizardBackSelector,
-												onInit: ams.getFunctionByName(data.amsWizardInit),
-												onShow: ams.getFunctionByName(data.amsWizardShow),
-												onNext: ams.getFunctionByName(data.amsWizardNext),
-												onPrevious: ams.getFunctionByName(data.amsWizardPrevious),
-												onFirst: ams.getFunctionByName(data.amsWizardFirst),
-												onLast: ams.getFunctionByName(data.amsWizardLast),
-												onBack: ams.getFunctionByName(data.amsWizardBack),
-												onFinish: ams.getFunctionByName(data.amsWizardFinish),
-												onTabChange: ams.getFunctionByName(data.amsWizardTabChange),
-												onTabClick: ams.getFunctionByName(data.amsWizardTabClick),
-												onTabShow: ams.getFunctionByName(data.amsWizardTabShow)
-											};
-											var settings = $.extend({}, dataOptions, data.amsWizardOptions);
-											settings = ams.executeFunctionByName(data.amsWizardInitCallback, wizard, settings) || settings;
-											var plugin = wizard.bootstrapWizard(settings);
-											ams.executeFunctionByName(data.amsWizardAfterInitCallback, wizard, plugin, settings);
-										});
-								   });
-				}
-			},
-
-			/**
 			 * TableDND plug-in
 			 */
 			tablednd: function(element) {
@@ -3889,6 +3925,12 @@
 														if (typeof(localTarget) === 'function') {
 															localTarget.call(table, dnd_table, rows);
 														} else {
+															if (!target.startsWith(window.location.protocol)) {
+																var location = data.amsLocation;
+																if (location) {
+																	target = location + '/' + target;
+																}
+															}
 															ams.ajax.post(target, {names: JSON.stringify(rows)});
 														}
 														// Restore row click handler
@@ -3909,6 +3951,48 @@
 			},
 
 			/**
+			 * Wizard plug-in
+			 */
+			wizard: function(element) {
+				var wizards = $('.wizard', element);
+				if (wizards.length > 0) {
+					ams.ajax.check($,
+								   ams.baseURL + 'ext/bootstrap-wizard-1.4.2' + ams.devext + '.js',
+								   function(first_load) {
+										wizards.each(function() {
+											var wizard = $(this);
+											var data = wizard.data();
+											var dataOptions = {
+												withVisible: data.amsWizardWithVisible === undefined ? true : data.amsWizardWithVisible,
+												tabClass: data.amsWizardTabClass,
+												firstSelector: data.amsWizardFirstSelector,
+												previousSelector: data.amsWizardPreviousSelector,
+												nextSelector: data.amsWizardNextSelector,
+												lastSelector: data.amsWizardLastSelector,
+												finishSelector: data.amsWizardFinishSelector,
+												backSelector: data.amsWizardBackSelector,
+												onInit: ams.getFunctionByName(data.amsWizardInit),
+												onShow: ams.getFunctionByName(data.amsWizardShow),
+												onNext: ams.getFunctionByName(data.amsWizardNext),
+												onPrevious: ams.getFunctionByName(data.amsWizardPrevious),
+												onFirst: ams.getFunctionByName(data.amsWizardFirst),
+												onLast: ams.getFunctionByName(data.amsWizardLast),
+												onBack: ams.getFunctionByName(data.amsWizardBack),
+												onFinish: ams.getFunctionByName(data.amsWizardFinish),
+												onTabChange: ams.getFunctionByName(data.amsWizardTabChange),
+												onTabClick: ams.getFunctionByName(data.amsWizardTabClick),
+												onTabShow: ams.getFunctionByName(data.amsWizardTabShow)
+											};
+											var settings = $.extend({}, dataOptions, data.amsWizardOptions);
+											settings = ams.executeFunctionByName(data.amsWizardInitCallback, wizard, settings) || settings;
+											var plugin = wizard.bootstrapWizard(settings);
+											ams.executeFunctionByName(data.amsWizardAfterInitCallback, wizard, plugin, settings);
+										});
+								   });
+				}
+			},
+
+			/**
 			 * TinyMCE plug-in
 			 */
 			tinymce: function(element) {
@@ -3928,50 +4012,58 @@
 					ams.ajax.check(window.tinymce,
 								   baseURL + '/tinymce' + ams.devext + '.js',
 								   function(first_load) {
-										if (first_load) {
-											ams.getScript(baseURL + '/jquery.tinymce' + ams.devext + '.js');
-											tinymce.baseURL = baseURL;
-											tinymce.suffix = ams.devext;
-											ams.skin.registerCleanCallback(cleanEditors);
+
+										function initEditors() {
+											editors.each(function() {
+												var editor = $(this);
+												var data = editor.data();
+												var dataOptions = {
+													theme: data.amsTinymceTheme || "modern",
+													language: ams.lang,
+													plugins: [
+														"advlist autosave autolink lists link image charmap print preview hr anchor pagebreak",
+														"searchreplace wordcount visualblocks visualchars code fullscreen",
+														"insertdatetime media nonbreaking save table contextmenu directionality",
+														"emoticons paste textcolor colorpicker textpattern"
+													],
+													toolbar1: data.amsTinymceToolbar1 || "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent",
+													toolbar2: data.amsTinymceToolbar2 || "forecolor backcolor emoticons | charmap link image media | fullscreen preview print | code",
+													content_css: data.amsTinymceContentCss,
+													formats: data.amsTinymceFormats,
+													style_formats: data.amsTinymceStyleFormats,
+													block_formats: data.amsTinymceBlockFormats,
+													valid_classes: data.amsTinymceValidClasses,
+													image_advtab: true,
+													image_list: ams.getFunctionByName(data.amsTinymceImageList) || data.amsTinymceImageList,
+													image_class_list: data.amsTinymceImageClassList,
+													link_list: ams.getFunctionByName(data.amsTinymceLinkList) || data.amsTinymceLinkList,
+													link_class_list: data.amsTinymceLinkClassList,
+													resize: true
+												};
+												if (data.amsTinymceExternalPlugins) {
+													var names = data.amsTinymceExternalPlugins.split(/\s+/);
+													for (var index in names) {
+														var pluginSrc = editor.data('ams-tinymce-plugin-' + names[index]);
+														tinymce.PluginManager.load(names[index], ams.getSource(pluginSrc));
+													}
+												}
+												var settings = $.extend({}, dataOptions, data.amsTinymceOptions);
+												settings = ams.executeFunctionByName(data.amsTinymceInitCallback, editor, settings) || settings;
+												var plugin = editor.tinymce(settings);
+												ams.executeFunctionByName(data.amsTinymceAfterInitCallback, editor, plugin, settings);
+											});
 										}
-										editors.each(function() {
-											var editor = $(this);
-											var data = editor.data();
-											var dataOptions = {
-												theme: "modern",
-												language: ams.lang,
-												plugins: [
-													"advlist autosave autolink lists link image charmap print preview hr anchor pagebreak",
-													"searchreplace wordcount visualblocks visualchars code",
-													"insertdatetime media nonbreaking save table contextmenu directionality",
-													"emoticons paste textcolor colorpicker textpattern"
-												],
-												toolbar1: "newdocument undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
-												toolbar2: "print preview media | forecolor backcolor emoticons | code",
-												content_css: data.amsTinymceContentCss,
-												formats: data.amsTinymceFormats,
-												style_formats: data.amsTinymceStyleFormats,
-												block_formats: data.amsTinymceBlockFormats,
-												valid_classes: data.amsTinymceValidClasses,
-												image_advtab: true,
-												image_list: ams.getFunctionByName(data.amsTinymceImageList) || data.amsTinymceImageList,
-												image_class_list: data.amsTinymceImageClassList,
-												link_list: ams.getFunctionByName(data.amsTinymceLinkList) || data.amsTinymceLinkList,
-												link_class_list: data.amsTinymceLinkClassList,
-												resize: true
-											};
-											if (data.amsTinymceExternalPlugins) {
-												var names = data.amsTinymceExternalPlugins.split(/\s+/);
-												for (var index in names) {
-													var pluginSrc = editor.data('ams-tinymce-plugin-' + names[index]);
-													tinymce.PluginManager.load(names[index], ams.getSource(pluginSrc));
-												}
-											}
-											var settings = $.extend({}, dataOptions, data.amsTinymceOptions);
-											settings = ams.executeFunctionByName(data.amsTinymceInitCallback, editor, settings) || settings;
-											var plugin = editor.tinymce(settings);
-											ams.executeFunctionByName(data.amsTinymceAfterInitCallback, editor, plugin, settings);
-										});
+
+										if (first_load) {
+											ams.getScript(baseURL + '/jquery.tinymce' + ams.devext + '.js', function() {
+												tinymce.baseURL = baseURL;
+												tinymce.suffix = ams.devext;
+												ams.skin.registerCleanCallback(cleanEditors);
+												initEditors();
+											});
+										} else {
+											initEditors();
+										}
 								   });
 				}
 			},
@@ -4206,8 +4298,8 @@
 									  function() {
 										ams.executeFunctionByName(data.amsCallback, self, data.amsCallbackOptions);
 									  });
-					} else if (globals.console) {
-						globals.console.warn("Undefined callback: " + data.amsCallback);
+					} else if (console) {
+						console.warn && console.warn("Undefined callback: " + data.amsCallback);
 					}
 				} else {
 					callback.call(self, data.amsCallbackOptions);
@@ -4361,9 +4453,9 @@
 					buttons: ams.i18n.BTN_OK_CANCEL
 				}, function(button) {
 					if (button === ams.i18n.BTN_OK) {
-						var table = link.parents('table');
+						var table = link.parents('table').first();
 						var location = table.data('ams-location') || '';
-						var tr = link.parents('tr');
+						var tr = link.parents('tr').first();
 						var deleteTarget = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json';
 						var objectName = tr.data('ams-element-name');
 						MyAMS.ajax.post(location + '/' + deleteTarget, {'object_name': objectName}, function(result, status) {
@@ -4503,7 +4595,7 @@
 			if (status === 'error') {
 				status = 'danger';
 			}
-			$('.alert-' + status, parent).remove();
+			$('.alert-' + status, parent).not('.persistent').remove();
 			var content = '<div class="' + (margin ? 'margin-10' : '') + ' alert alert-block alert-' + status + ' padding-5 fade in">' +
 				'<a class="close" data-dismiss="alert"><i class="fa fa-check"></i></a>' +
 				'<h4 class="alert-heading">' +
@@ -5228,6 +5320,11 @@
 		$(document).on('reset', 'form', function(e) {
 			var form = $(this);
 			setTimeout(function() {
+				$('INPUT.select2[type="hidden"]', form).each(function() {
+					var input = $(this);
+					var select = input.data('select2');
+					input.select2('val', input.data('ams-select2-input-value').split(select.opts.separator));
+				});
 				form.find('.select2').trigger('change');
 				$('[data-ams-reset-callback]', form).each(function() {
 					var element = $(this);
@@ -5403,6 +5500,7 @@
 		BTN_YES_NO: "[Yes][No]",
 
 		CLIPBOARD_COPY: "Copy to clipboard with Ctrl+C, and Enter",
+		CLIPBOARD_COPY_OK: "Text copied to clipboard",
 
 		FORM_CHANGED_WARNING: "Some changes were not saved. These updates will be lost if you leave this page.",
 		DELETE_WARNING: "This change can't be undone. Are you sure that you want to delete this element?",