src/ztfy/myams/resources/js/myams.js
changeset 206 02a40997d8cb
parent 203 108498416bee
child 210 a4497eed4ff7
--- a/src/ztfy/myams/resources/js/myams.js	Fri May 12 14:03:02 2017 +0200
+++ b/src/ztfy/myams/resources/js/myams.js	Thu Oct 26 14:45:34 2017 +0200
@@ -14,6 +14,8 @@
 
 	"use strict";
 
+	var console = globals.console;
+
 	/**
 	 * String prototype extensions
 	 */
@@ -100,7 +102,7 @@
 	 */
 	if ($.scrollbarWidth === undefined) {
 		$.scrollbarWidth = function() {
-			var parent = $('<div style="width:50px; height:50px; overflow:auto"><div/></div>').appendTo('body');
+			var parent = $('<div style="width: 50px; height: 50px; overflow: auto"><div/></div>').appendTo('body');
 			var child = parent.children();
 			var width = child.innerWidth() - child.height(99).innerWidth();
 			parent.remove();
@@ -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.debug && console.debug(this, arguments);
 		}
 	};
 
@@ -688,14 +690,55 @@
 			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: text.length > 1
+											  ? ams.i18n.CLIPBOARD_TEXT_COPY_OK
+											  : ams.i18n.CLIPBOARD_CHARACTER_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 +752,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 +772,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 +796,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 +905,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) + "%");
 			}
 		},
 
@@ -985,9 +1032,11 @@
 					break;
 				case 'info':
 				case 'success':
-					ams.form.resetChanged(form);
-					if (result.close_form !== false) {
-						ams.dialog.close(form);
+					if (form !== undefined) {
+						ams.form.resetChanged(form);
+						if (result.close_form !== false) {
+							ams.dialog.close(form);
+						}
 					}
 					break;
 				case 'message':
@@ -996,29 +1045,47 @@
 				case 'notify':
 				case 'callback':
 				case 'callbacks':
-					ams.form.resetChanged(form);
-					if (result.close_form !== false) {
-						ams.dialog.close(form);
+					if (form !== undefined) {
+						ams.form.resetChanged(form);
+						if (result.close_form !== false) {
+							ams.dialog.close(form);
+						}
 					}
 					break;
 				case 'modal':
 					ams.dialog.open(result.location);
 					break;
 				case 'reload':
-					ams.form.resetChanged(form);
-					if (result.close_form !== false) {
-						ams.dialog.close(form);
+					if (form !== undefined) {
+						ams.form.resetChanged(form);
+						if (result.close_form !== false) {
+							ams.dialog.close(form);
+						}
 					}
 					url = result.location || window.location.hash;
 					if (url.startsWith('#')) {
 						url = url.substr(1);
 					}
-					ams.skin.loadURL(url, result.target || target || '#content');
+					var loadTarget = $(result.target || target || '#content');
+					ams.skin.loadURL(url, loadTarget, {
+						preLoadCallback: ams.getFunctionByName(result.pre_reload) || function() {
+							$('[data-ams-pre-reload]', loadTarget).each(function() {
+								ams.executeFunctionByName($(this).data('ams-pre-reload'));
+							});
+						},
+						afterLoadCallback: ams.getFunctionByName(result.post_reload) || function () {
+							$('[data-ams-post-reload]', loadTarget).each(function () {
+								ams.executeFunctionByName($(this).data('ams-post-reload'));
+							});
+						}
+					});
 					break;
 				case 'redirect':
-					ams.form.resetChanged(form);
-					if (result.close_form === true) {
-						ams.dialog.close(form);
+					if (form !== undefined) {
+						ams.form.resetChanged(form);
+						if (result.close_form === true) {
+							ams.dialog.close(form);
+						}
 					}
 					url = result.location || window.location.href;
 					if (result.window) {
@@ -1032,8 +1099,8 @@
 					}
 					break;
 				default:
-					if (globals.console) {
-						globals.console.log("Unhandled status: " + status);
+					if (console) {
+						console.log && console.log("Unhandled status: " + status);
 					}
 			}
 
@@ -1123,6 +1190,20 @@
 			if (result.event) {
 				form.trigger(result.event, result.event_options);
 			}
+			if (result.events) {
+				var event;
+				if (form === undefined) {
+					form = $(document);
+				}
+				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 +1211,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);
+					}
 				}
 			}
 		}
@@ -1325,6 +1410,16 @@
 		 * @param element: the parent element
 		 */
 		init: function(element) {
+
+			$('FORM', element).each(function() {
+				var form = $(this);
+				// Store value of hidden inputs
+				$('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) {
@@ -2018,10 +2113,15 @@
 						// set widget status message
 						var widgetData = errors.widgets[index];
 						var widget = $('[name="' + widgetData.name + '"]', form);
-						widget.parents('label:first')
-								.removeClassPrefix('state-')
-								.addClass('state-error')
-								.after('<span for="name" class="state-error">' + widgetData.message + '</span>');
+						if (!widget.exists()) {
+							widget = $('[name="' + widgetData.name + ':list"]', form);
+						}
+						if (widget.exists()) {
+							widget.parents('label:first')
+								  .removeClassPrefix('state-')
+								  .addClass('state-error')
+								  .after('<span for="name" class="state-error">' + widgetData.message + '</span>');
+						}
 						// complete form alert message
 						if (widgetData.label) {
 							message.push(widgetData.label + ' : ' + widgetData.message);
@@ -2336,6 +2436,19 @@
 	 */
 	MyAMS.helpers = {
 
+		/** Sort DOM elements into selected container */
+		sort: function(container, attribute) {
+			if (!attribute) {
+				attribute = 'weight';
+			}
+			var childs = container.children();
+			childs.sort(function(a, b) {
+				return +$(a).data(attribute) - +$(b).data(attribute);
+			}).each(function() {
+				container.append(this);
+			});
+		},
+
 		/** Clear Select2 slection */
 		select2ClearSelection: function() {
 			var source = $(this);
@@ -2363,6 +2476,14 @@
 			}
 		},
 
+		/** Select2 'select-all' helper */
+		select2SelectAllHelper: function() {
+			var source = $(this);
+			var parent = source.parents('label:first');
+			var input = $('.select2', parent);
+			input.select2('data', input.data('ams-select2-data'));
+		},
+
 		/** Select2 query results callback */
 		select2QueryUrlResultsCallback: function(data, page, context) {
 			switch (data.status) {
@@ -2701,8 +2822,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;
 			}
@@ -2770,9 +2891,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',
@@ -3011,6 +3134,7 @@
 						var dataOptions = {
 							items: data.amsSortableItems,
 							handle: data.amsSortableHandle,
+							helper: data.amsSortableHelper,
 							connectWith: data.amsSortableConnectwith,
 							start: ams.getFunctionByName(data.amsSortableStart),
 							over: ams.getFunctionByName(data.amsSortableOver),
@@ -3346,7 +3470,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;
@@ -3378,7 +3504,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;
@@ -3409,7 +3538,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;
@@ -3797,6 +3927,74 @@
 			},
 
 			/**
+			 * TableDND plug-in
+			 */
+			tablednd: function(element) {
+				var tables = $('.table-dnd', element);
+				if (tables.length > 0) {
+					ams.ajax.check($.fn.tableDnD,
+								   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
+								   function(first_load) {
+										tables.each(function() {
+											var table = $(this);
+											var data = table.data();
+											if (data.amsTabledndDragHandle) {
+												$('tr', table).addClass('no-drag-handle');
+											} else {
+												$(table).on('mouseover', 'tr', function () {
+													$(this.cells[0]).addClass('drag-handle');
+												}).on('mouseout', 'tr', function () {
+													$(this.cells[0]).removeClass('drag-handle');
+												});
+											}
+											var dataOptions = {
+												onDragClass: data.amsTabledndDragClass || 'dragging-row',
+												onDragStart: ams.getFunctionByName(data.amsTabledndDragStart),
+												dragHandle: data.amsTabledndDragHandle,
+												scrollAmount: data.amsTabledndScrollAmount,
+												onAllowDrop: data.amsTabledndAllowDrop,
+												onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) {
+													var target = data.amsTabledndDropTarget;
+													if (target) {
+														// Disable row click handler
+														$(row).data('ams-disabled-handlers', 'click');
+														var rows = [];
+														$(dnd_table.rows).each(function() {
+															var rowId = $(this).data('ams-element-name');
+															if (rowId) {
+																rows.push(rowId);
+															}
+														});
+														var localTarget = ams.getFunctionByName(target);
+														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
+														setTimeout(function() {
+															$(row).removeData('ams-disabled-handlers');
+														}, 50);
+													}
+													return false;
+												}
+											};
+											var settings = $.extend({}, dataOptions, data.amsTabledndOptions);
+											settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings;
+											var plugin = table.tableDnD(settings);
+											ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings);
+										});
+								   });
+				}
+			},
+
+			/**
 			 * Wizard plug-in
 			 */
 			wizard: function(element) {
@@ -3839,63 +4037,81 @@
 			},
 
 			/**
-			 * TableDND plug-in
+			 * TinyMCE plug-in
 			 */
-			tablednd: function(element) {
-				var tables = $('.table-dnd', element);
-				if (tables.length > 0) {
-					ams.ajax.check($.fn.tableDnD,
-								   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
+			tinymce: function(element) {
+
+				function cleanEditors() {
+					$('.tinymce', $(this)).each(function() {
+						var editor = tinymce.get($(this).attr('id'));
+						if (editor) {
+							editor.remove();
+						}
+					});
+				}
+
+				var editors = $('.tinymce', element);
+				if (editors.length > 0) {
+					var baseURL = ams.baseURL + 'ext/tinymce' + (ams.devmode ? '/dev' : '');
+					ams.ajax.check(window.tinymce,
+								   baseURL + '/tinymce' + ams.devext + '.js',
 								   function(first_load) {
-										tables.each(function() {
-											var table = $(this);
-											var data = table.data();
-											if (data.amsTabledndDragHandle) {
-												$('tr', table).addClass('no-drag-handle');
-											} else {
-												$(table).on('mouseover', 'tr', function () {
-													$(this.cells[0]).addClass('drag-handle');
-												}).on('mouseout', 'tr', function () {
-													$(this.cells[0]).removeClass('drag-handle');
-												});
-											}
-											var dataOptions = {
-												onDragClass: data.amsTabledndDragClass || 'dragging-row',
-												onDragStart: ams.getFunctionByName(data.amsTabledndDragStart),
-												dragHandle: data.amsTabledndDragHandle,
-												scrollAmount: data.amsTabledndScrollAmount,
-												onAllowDrop: data.amsTabledndAllowDrop,
-												onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) {
-													var target = data.amsTabledndDropTarget;
-													if (target) {
-														// Disable row click handler
-														$(row).data('ams-disabled-handlers', 'click');
-														var rows = [];
-														$(dnd_table.rows).each(function() {
-															var rowId = $(this).data('ams-element-name');
-															if (rowId) {
-																rows.push(rowId);
-															}
-														});
-														var localTarget = ams.getFunctionByName(target);
-														if (typeof(localTarget) === 'function') {
-															localTarget.call(table, dnd_table, rows);
-														} else {
-															ams.ajax.post(target, {names: JSON.stringify(rows)});
-														}
-														// Restore row click handler
-														setTimeout(function() {
-															$(row).removeData('ams-disabled-handlers');
-														}, 50);
+
+										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 autoresize"
+													],
+													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,
+													height: 50,
+													min_height: 50,
+													autoresize_min_height: 50,
+													autoresize_max_height: 500,
+													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));
 													}
-													return false;
 												}
-											};
-											var settings = $.extend({}, dataOptions, data.amsTabledndOptions);
-											settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings;
-											var plugin = table.tableDnD(settings);
-											ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings);
-										});
+												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();
+										}
 								   });
 				}
 			},
@@ -3965,6 +4181,10 @@
 										fancyboxes.each(function() {
 											var fancybox = $(this);
 											var data = fancybox.data();
+											var elements = fancybox;
+											if (data.amsFancyboxElements) {
+												elements = $(data.amsFancyboxElements, fancybox);
+											}
 											var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
 											if (helpers.length > 0) {
 												for (var index=0; index < helpers.length; index++) {
@@ -3991,18 +4211,52 @@
 												type: data.amsFancyboxType,
 												padding: data.amsFancyboxPadding || 10,
 												margin: data.amsFancyboxMargin || 10,
+												loop: data.amsFancyboxLoop,
 												beforeLoad: ams.getFunctionByName(data.amsFancyboxBeforeLoad) || function() {
-													this.title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this) || $(this.element).attr('original-title') || $(this.element).attr('title');
+													var title;
+													if (data.amsFancyboxTitleGetter) {
+														title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this);
+													}
+													if (!title) {
+														var content = $('*:first', this.element);
+														title = content.attr('original-title') || content.attr('title');
+														if (!title) {
+															title = $(this.element).attr('original-title') || $(this.element).attr('title');
+														}
+													}
+													this.title = title;
 												},
+												afterLoad: ams.getFunctionByName(data.amsFancyboxAfterLoad),
 												helpers: {
 													title: {
 														type: 'inside'
 													}
 												}
 											};
+											if (helpers.length > 0) {
+												for (index = 0; index < helpers.length; index++) {
+													helper = helpers[index];
+													switch (helper) {
+														case 'buttons':
+															dataOptions.helpers.buttons = {
+																position: data.amsFancyboxButtonsPosition || 'top'
+															};
+															break;
+														case 'thumbs':
+															dataOptions.helpers.thumbs = {
+																width: data.amsFancyboxThumbsWidth || 50,
+																height: data.amsFancyboxThumbsHeight || 50
+															};
+															break;
+														case 'media':
+															dataOptions.helpers.media = true;
+															break;
+													}
+												}
+											}
 											var settings = $.extend({}, dataOptions, data.amsFancyboxOptions);
 											settings = ams.executeFunctionByName(data.amsFancyboxInitCallback, fancybox, settings) || settings;
-											var plugin = fancybox.fancybox(settings);
+											var plugin = elements.fancybox(settings);
 											ams.executeFunctionByName(data.amsFancyboxAfterInitCallback, fancybox, plugin, settings);
 										});
 								   });
@@ -4086,8 +4340,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);
@@ -4237,13 +4491,14 @@
 				var link = $(this);
 				MyAMS.skin.bigBox({
 					title: ams.i18n.WARNING,
-					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + ams.i18n.DELETE_WARNING,
+					content: '<i class="text-danger fa fa-fw fa-bell"></i>&nbsp; ' + ams.i18n.DELETE_WARNING,
+					status: 'info',
 					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) {
@@ -4253,6 +4508,9 @@
 								} else {
 									tr.remove();
 								}
+								if (result.handle_json) {
+									MyAMS.ajax.handleJSON(result);
+								}
 							} else {
 								MyAMS.ajax.handleJSON(result);
 							}
@@ -4383,7 +4641,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">' +
@@ -4624,6 +4882,9 @@
 				dataType: 'html',
 				cache: false,
 				beforeSend: function() {
+					if (options && options.preLoadCallback) {
+						ams.executeFunctionByName(options.preLoadCallback, this);
+					}
 					ams.skin.cleanContainer(container);
 					container.html('<h1 class="loading"><i class="fa fa-cog fa-spin"></i> ' + ams.i18n.LOADING + ' </h1>');
 					if (container[0] === $('#content')[0]) {
@@ -4775,9 +5036,11 @@
 				var request = xhr();
 				if (request && (typeof(request.addEventListener) === "function")) {
 					var that = this;
-					request.addEventListener("progress", function(evt) {
-						that.progress(evt);
-					}, false);
+					if (that && that.progress) {
+						request.addEventListener("progress", function (evt) {
+							that.progress(evt);
+						}, false);
+					}
 				}
 				return request;
 			}
@@ -4893,7 +5156,7 @@
 				title : "<i class='fa fa-sign-out txt-color-orangeDark'></i> " + ams.i18n.LOGOUT +
 						" <span class='txt-color-orangeDark'><strong>" + $('#show-shortcut').text() + "</strong></span> ?",
 				content : ams.i18n.LOGOUT_COMMENT,
-				buttons : '['+ams.i18n.BTN_NO+']['+ams.i18n.BTN_YES+']'
+				buttons : ams.i18n.BTN_YES_NO
 			}, function(ButtonPressed) {
 				if (ButtonPressed === ams.i18n.BTN_YES) {
 					ams.root.addClass('animated fadeOutUp');
@@ -4982,28 +5245,32 @@
 					// Standard AJAX or browser URL call
 					// Convert %23 chars to #
 					href = href.replace(/\%23/, '#');
-					var target = link.data('ams-target');
-					if (target) {
-						ams.form.confirmChangedForm(target, function () {
-							ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback'));
-						});
+					if (e.ctrlKey) {
+						window.open(href);
 					} 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 () {
+						var target = link.data('ams-target');
+						if (target) {
+							ams.form.confirmChangedForm(target, function () {
+								ams.skin.loadURL(href, target, link.data('ams-link-options'), link.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;
+											}, 50);
+										} else {
 											window.location.hash = href;
-										}, 50);
-									} else {
-										window.location.hash = href;
+										}
 									}
+								} else {
+									window.location = href;
 								}
-							} else {
-								window.location = href;
-							}
-						});
+							});
+						}
 					}
 				}
 			});
@@ -5108,6 +5375,13 @@
 		$(document).on('reset', 'form', function(e) {
 			var form = $(this);
 			setTimeout(function() {
+				$('.alert-danger, SPAN.state-error', form).not('.persistent').remove();
+				$('LABEL.state-error', form).removeClass('state-error');
+				$('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);
@@ -5261,6 +5535,7 @@
 		WAIT: "Please wait!",
 		FORM_SUBMITTED: "This form was already submitted...",
 		NO_SERVER_RESPONSE: "No response from server!",
+
 		ERROR_OCCURED: "An error occured!",
 		ERRORS_OCCURED: "Some errors occured!",
 
@@ -5282,6 +5557,8 @@
 		BTN_YES_NO: "[Yes][No]",
 
 		CLIPBOARD_COPY: "Copy to clipboard with Ctrl+C, and Enter",
+		CLIPBOARD_CHARACTER_COPY_OK: "Character copied to clipboard",
+		CLIPBOARD_TEXT_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?",
@@ -5304,7 +5581,19 @@
 		SELECT2_FREETAG_PREFIX: "Free text: ",
 
 		DT_COLUMNS: "Columns"
-
+	}
+
+	MyAMS.plugins.i18n = {
+		widgets: {},
+		validate: {},
+		datatables: {},
+		fancybox: {
+			ERROR: "Can't load requested content.",
+			RETRY: "Please check URL or try again later.",
+			CLOSE: "Close",
+			NEXT: "Next",
+			PREVIOUS: "Previous"
+		}
 	};