src/pyams_skin/resources/js/myams-widgets.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
equal deleted inserted replaced
565:318533413200 566:a1707c607eec
     1 /*
       
     2  * MyAMS extensions for widgets handling
       
     3  * Version 0.1.0
       
     4  * ©2014 Thierry Florac <tflorac@ulthar.net>
       
     5  */
       
     6 
       
     7 (function($, globals) {
       
     8 
       
     9 	'use strict';
       
    10 
       
    11 	/* Private functions */
       
    12 	function checkValue(value) {
       
    13 		if (value < 10) {
       
    14 			value = '0' + value;
       
    15 		}
       
    16 		return value;
       
    17 	}
       
    18 
       
    19 	function getPastTimeStamp(value, options) {
       
    20 		var date = new Date(value);
       
    21 		var month = checkValue(date.getMonth() + 1);
       
    22 		var day = checkValue(date.getDate());
       
    23 		var year = checkValue(date.getFullYear());
       
    24 		var hours = checkValue(date.getHours());
       
    25 		var minutes = checkValue(date.getMinutes());
       
    26 		var seconds = checkValue(date.getSeconds());
       
    27 		return options.timestampFormat.replace(/%d%/g, day)
       
    28 			.replace(/%m%/g, month)
       
    29 			.replace(/%y%/g, year)
       
    30 			.replace(/%h%/g, hours)
       
    31 			.replace(/%i%/g, minutes)
       
    32 			.replace(/%s%/g, seconds);
       
    33 	}
       
    34 
       
    35 
       
    36 	var ams = globals.MyAMS;
       
    37 
       
    38 
       
    39 	function Widget(element, options) {
       
    40 		this.widget = element;
       
    41 		this.options = $.extend({}, MyAMSWidget.defaults, options);
       
    42 		this.grid = this.widget.parents(this.options.grid);
       
    43 		this.hasGrid = this.grid.exists();
       
    44 		this.gridId = this.grid.attr('id');
       
    45 		this.controls = this.options.controls;
       
    46 		this.toggleClass = this.options.toggleClass.split('|');
       
    47 		this.editClass = this.options.editClass.split('|');
       
    48 		this.fullscreenClass = this.options.fullscreenClass.split('|');
       
    49 		this.customClass = this.options.customClass.split('|');
       
    50 		this.init();
       
    51 	}
       
    52 
       
    53 	Widget.prototype = {
       
    54 
       
    55 		init: function() {
       
    56 			var self = this;
       
    57 			var widget;
       
    58 
       
    59 			if (self.options.rtl === true) {
       
    60 				$('body').addClass('rtl');
       
    61 			}
       
    62 			self.grid.each(function() {
       
    63 				$(this).addClass('sortable-grid');
       
    64 			});
       
    65 			self._getSettings();
       
    66 			if (self.hasGrid && self.storage) {
       
    67 
       
    68 				var key;
       
    69 				if (self.position) {
       
    70 					var position = JSON.parse(self.position);
       
    71 					for (key in position.grid) {
       
    72 						if (!position.grid.hasOwnProperty(key)) {
       
    73 							continue;
       
    74 						}
       
    75 						var changeOrder = self.grid.find(self.options.subgrid + '.sortable-grid').eq(key);
       
    76 						for (var key2 in position.grid[key].section) {
       
    77 							if (!position.grid[key].section.hasOwnProperty(key2)) {
       
    78 								continue;
       
    79 							}
       
    80 							changeOrder.append($('#' + position.grid[key].section[key2].id));
       
    81 						}
       
    82 					}
       
    83 				}
       
    84 				if (self.settings) {
       
    85 					var settings = JSON.parse(self.settings);
       
    86 					for (key in settings.widget) {
       
    87 						if (!settings.widget.hasOwnProperty(key)) {
       
    88 							continue;
       
    89 						}
       
    90 						widget = settings.widget[key];
       
    91 						if (!widget.id) {
       
    92 							continue;
       
    93 						}
       
    94 						var mywidget = $('#' + widget.id);
       
    95 						if (!mywidget.exists()) {
       
    96 							continue;
       
    97 						}
       
    98 						if (widget.style) {
       
    99 							mywidget.removeClassPrefix('ams-widget-color-')
       
   100 								.addClass(widget.style)
       
   101 								.attr('data-widget-attstyle', widget.style);
       
   102 						}
       
   103 						if (widget.hidden === 1) {
       
   104 							mywidget.hide(1);
       
   105 						} else {
       
   106 							mywidget.show(1)
       
   107 								.removeAttr('data-widget-hidden');
       
   108 						}
       
   109 						if (widget.collapsed === 1) {
       
   110 							mywidget.addClass('ams-widget-collapsed')
       
   111 								.children('div')
       
   112 								.hide(1);
       
   113 						}
       
   114 						var title = mywidget.children('header').children('h2');
       
   115 						if (title.text() !== widget.title) {
       
   116 							title.text(widget.title);
       
   117 						}
       
   118 					}
       
   119 				}
       
   120 			}
       
   121 			widget = self.widget;
       
   122 			var data = widget.data();
       
   123 			var data_options = {
       
   124 				grid: data.amsWidgetGrid,
       
   125 				subgrid: data.amsWudgetSubgrid,
       
   126 				widgets: data.amsWidgetWidgets,
       
   127 				controls: data.amsWidgetControls,
       
   128 				storage: data.amsWidgetStorage,
       
   129 				deleteSettingsKey: data.amsWidgetDeleteSettingsKey,
       
   130 				deletePositionKey: data.amsWidgetDeletePositionKey,
       
   131 				sortable: data.amsWidgetSortable,
       
   132 				hiddenButtons: data.amsWidgetHiddenButtons,
       
   133 				toggleButton: data.amsWidgetToggleButton,
       
   134 				toggleClass: data.amsWidgetToggleClass,
       
   135 				onToggle: ams.getFunctionByName(data.amsWidgetToggleCallback),
       
   136 				deleteButton: data.amsWidgetDeleteButton,
       
   137 				deleteClass: data.amsWidgetDeleteClass,
       
   138 				onDelete: ams.getFunctionByName(data.amsWidgetDeleteCallback),
       
   139 				editButton: data.amsWidgetEditButton,
       
   140 				editPlaceholder: data.amsWidgetEditPlaceholder,
       
   141 				editClass: data.amsWidgetEditClass,
       
   142 				onEdit: ams.getFunctionByName(data.amsWidgetEditCallback),
       
   143 				fullscreenButton: data.amsWidgetFullscreenButton,
       
   144 				fullscreenClass: data.amsWidgetFullscreenClass,
       
   145 				fullscreenDiff: data.amsWidgetFullscreenDiff,
       
   146 				onFullscreen: ams.getFunctionByName(data.amsWidgetFullscreenCallback),
       
   147 				customButton: data.amsWidgetCustomButton,
       
   148 				customClass: data.amsWidgetCustomClass,
       
   149 				customStart: ams.getFunctionByName(data.amsWidgetCustomStartCallback),
       
   150 				customEnd: ams.getFunctionByName(data.amsWidgetCustomEndCallback),
       
   151 				buttonsOrder: data.amsWidgetButtonsOrder,
       
   152 				opacity: data.amsWidgetOpacity,
       
   153 				dragHandle: data.amsWidgetDragHandle,
       
   154 				placeholderClass: data.amsWidgetPlaceholderClass,
       
   155 				indicator: data.amsWidgetIndicator,
       
   156 				indicatorTime: data.amsWidgetIndicatorTime,
       
   157 				ajax: data.amsWidgetAjax,
       
   158 				timestampPlaceholder: data.amsWidgetTimestampPlaceholder,
       
   159 				timestampFormat: data.amsWidgetTimestampFormat,
       
   160 				refreshButton: data.amsWidgetRefreshButton,
       
   161 				refreshClass: data.amsWidgetRefreshClass,
       
   162 				errorLabel: data.amsWidgetErrorLabel,
       
   163 				updatedLabel: data.amsWidgetUpdatedLabel,
       
   164 				refreshLabel: data.amsWidgetRefreshLabel,
       
   165 				deleteLabel: data.amsWidgetDeleteLabel,
       
   166 				afterLoad: ams.getFunctionByName(data.amsWidgetAfterLoadCallback),
       
   167 				rtl: data.amsWidgetRtl,
       
   168 				onChange: ams.getFunctionByName(data.amsWidgetChangeCallback),
       
   169 				onSave: ams.getFunctionByName(data.amsWidgetSaveCallback),
       
   170 				ajax_nav: ams.ajax_nav
       
   171 			};
       
   172 			var widgetOptions = $.extend({}, self.options, data_options);
       
   173 			var header = widget.children('header');
       
   174 			if (!header.parent().attr('role')) {
       
   175 
       
   176 				var customBtn,
       
   177 					deleteBtn,
       
   178 					editBtn,
       
   179 					fullscreenBtn,
       
   180 					toggleBtn,
       
   181 					refreshBtn;
       
   182 				if (data.widgetHidden === true) {
       
   183 					widget.hide();
       
   184 				}
       
   185 				if (data.widgetCollapsed === true) {
       
   186 					widget.addClass('ams-widget-collapsed')
       
   187 						.children('div').hide();
       
   188 				}
       
   189 				if (widgetOptions.customButton &&
       
   190 					(data.widgetCustombutton === undefined) &&
       
   191 					(self.customClass[0].length !== 0)) {
       
   192 					customBtn = '<a href="#" class="button-icon ams-widget-custom-btn"><i class="' + self.customClass[0] + '"></i></a>';
       
   193 				} else {
       
   194 					customBtn = "";
       
   195 				}
       
   196 				if (widgetOptions.deleteButton && (data.widgetDeleteButton === undefined)) {
       
   197 					deleteBtn = '<a href="#" class="button-icon ams-widget-delete-btn hint" title="' + MyAMSWidget.i18n.DELETE_BTN + '" data-ams-hint-gravity="se">' +
       
   198 						'<i class="' + widgetOptions.deleteClass + '"></i></a>';
       
   199 				} else {
       
   200 					deleteBtn = "";
       
   201 				}
       
   202 				if (widgetOptions.editButton && (data.widgetEditButton === undefined)) {
       
   203 					var editClass = widgetOptions.editClass.split('|')[0];
       
   204 					editBtn = '<a href="#" class="button-icon ams-widget-edit-btn hint" title="' + MyAMSWidget.i18n.EDIT_BTN + '" data-ams-hint-gravity="se">' +
       
   205 						'<i class="' + editClass + '"></i></a>';
       
   206 				} else {
       
   207 					editBtn = "";
       
   208 				}
       
   209 				if (widgetOptions.fullscreenButton && (data.widgetFullscreenButton === undefined)) {
       
   210 					var fullscreenClass = widgetOptions.fullscreenClass.split('|')[0];
       
   211 					fullscreenBtn = '<a href="#" class="button-icon ams-widget-fullscreen-btn hint" title="' + MyAMSWidget.i18n.FULLSCREEN_BTN + '" data-ams-hint-gravity="se">' +
       
   212 						'<i class="' + fullscreenClass + '"></i></a>';
       
   213 				} else {
       
   214 					fullscreenBtn = "";
       
   215 				}
       
   216 				if (widgetOptions.toggleButton && (data.widgetToggleButton === undefined)) {
       
   217 					var toggleClass = widgetOptions.toggleClass.split('|');
       
   218 					var toggleSettings;
       
   219 					if ((widget.dataWidgetCollapsed === true) ||
       
   220 						widget.hasClass('ams-widget-collapsed')) {
       
   221 						toggleSettings = toggleClass[1];
       
   222 					} else {
       
   223 						toggleSettings = toggleClass[0];
       
   224 					}
       
   225 					toggleBtn = '<a href="#" class="button-icon ams-widget-toggle-btn hint" title="' + MyAMSWidget.i18n.COLLAPSE_BTN + '" data-ams-hint-gravity="se">' +
       
   226 						'<i class="' + toggleSettings + '"></i></a>';
       
   227 				} else {
       
   228 					toggleBtn = "";
       
   229 				}
       
   230 				if (widgetOptions.refreshButton &&
       
   231 					(data.widgetRefreshButton === undefined) &&
       
   232 					data.widgetLoad) {
       
   233 					refreshBtn = '<a href="#" class="button-icon ams-widget-refresh-btn hint" title="' + MyAMSWidget.i18n.REFRESH_BTN + '" data-loading-text="&nbsp;&nbsp;' + MyAMSWidget.i18n.LOADING_MSG + '&nbsp;" data-ams-hint-gravity="se">' +
       
   234 						'<i class="' + widgetOptions.refreshClass + '"></i></a>';
       
   235 				} else {
       
   236 					refreshBtn = "";
       
   237 				}
       
   238 				var buttons = widgetOptions.buttonsOrder.replace(/%refresh%/, refreshBtn)
       
   239 					.replace(/%custom%/, customBtn)
       
   240 					.replace(/%edit%/, editBtn)
       
   241 					.replace(/%toggle%/, toggleBtn)
       
   242 					.replace(/%fullscreen%/, fullscreenBtn)
       
   243 					.replace(/%delete%/, deleteBtn);
       
   244 				if (refreshBtn || customBtn || editBtn || toggleBtn || fullscreenBtn || deleteBtn) {
       
   245 					header.prepend('<div class="ams-widget-ctrls">' + buttons + '</div>');
       
   246 				}
       
   247 				if (widgetOptions.sortable && (data.widgetSortable === undefined)) {
       
   248 					widget.addClass('ams-widget-sortable');
       
   249 				}
       
   250 				var placeholder = widget.find(widgetOptions.editPlaceholder);
       
   251 				if (placeholder.length > 0) {
       
   252 					placeholder.find('input').val($.trim(header.children('h2').text()));
       
   253 				}
       
   254 				header.append('<span class="ams-widget-loader"><i class="fa fa-refresh fa-spin"></i></span>');
       
   255 				widget.attr('role', 'widget')
       
   256 					.children('div').attr('role', 'content')
       
   257 					.prev('header').attr('role', 'heading')
       
   258 					.children('div').attr('role', 'menu');
       
   259 				ams.plugins && ams.plugins.enabled.hint && ams.plugins.enabled.hint(header);
       
   260 			}
       
   261 			widget.data('widget-options', widgetOptions);
       
   262 			if (self.options.hiddenButtons) {
       
   263 				$(self.controls).hide();
       
   264 			}
       
   265 			widget.find("[data-widget-load]").each(function() {
       
   266 				var item = $(this),
       
   267 					header = item.children(),
       
   268 					path = item.data('widget-load'),
       
   269 					reloadTime = item.data('widget-refresh') * 1000,
       
   270 					loader = header;
       
   271 				if (item.find('.ams-widget-ajax-placeholder').length <= 0) {
       
   272 					item.children('widget-body').append('<div class="ams-widget-ajax-placeholder">' + self.options.loadingLabel + "</div>");
       
   273 					if (reloadTime > 0) {
       
   274 						self.loadAjaxFile(item, path, header);
       
   275 						setInterval(function() {
       
   276 							self._loadAjaxFile(item, path, header);
       
   277 						}, reloadTime);
       
   278 					} else {
       
   279 						self._loadAjaxFile(item, path, header);
       
   280 					}
       
   281 				}
       
   282 			});
       
   283 			if (self.options.hiddenButtons) {
       
   284 				self.widget.children('header').hover(function() {
       
   285 					$(this).children(self.controls).stop(true, true).fadeTo(100, 1);
       
   286 				}, function() {
       
   287 					$(this).children(self.controls).stop(true, true).fadeTo(100, 0);
       
   288 				});
       
   289 			}
       
   290 			self._setClickEvents();
       
   291 			$(self.options.deleteSettingsKey).on(self.clickEvent, this, function(e) {
       
   292 				if (self.storage && globals.confirm) {
       
   293 					var cleared = globals.confirm(self.options.settingsKeyLabel);
       
   294 					if (cleared) {
       
   295 						self.storage.removeItem(self.settingsKey);
       
   296 					}
       
   297 				}
       
   298 				e.preventDefault();
       
   299 			});
       
   300 			$(self.options.deletePositionKey).on(self.clickEvent, this, function(e) {
       
   301 				if (self.storage && globals.confirm) {
       
   302 					var cleared = globals.confirm(self.options.positionKeyLabel);
       
   303 					if (cleared) {
       
   304 						self.storage.removeItem(self.positionKey);
       
   305 					}
       
   306 				}
       
   307 				e.preventDefault();
       
   308 			});
       
   309 			if (self.storage) {
       
   310 				if (self.settingsKey === null || self.settingsKey.length < 1) {
       
   311 					self._saveWidgetSettings();
       
   312 				}
       
   313 				if (self.positionKey === null || self.positionKey.length < 1) {
       
   314 					self._saveWidgetPosition();
       
   315 				}
       
   316 			}
       
   317 			self.grid.data('ams-widgets-loaded', true);
       
   318 		},
       
   319 
       
   320 		destroy: function() {
       
   321 			var self = this;
       
   322 			self.widgets.off('click', self._setClickEvents());
       
   323 			self.element.removeData('AMSWidget');
       
   324 		},
       
   325 
       
   326 		_getSettings: function() {
       
   327 			var self = this;
       
   328 			if (!self.hasGrid || !self.gridId) {
       
   329 				self.storage = null;
       
   330 			} else {
       
   331 				switch (self.options.storage) {
       
   332 					case 'local':
       
   333 						self.storage = localStorage;
       
   334 						break;
       
   335 					case 'session':
       
   336 						self.storage = sessionStorage;
       
   337 						break;
       
   338 					default:
       
   339 						self.storage = null;
       
   340 				}
       
   341 			}
       
   342 			var use_storage = (self.storage !== null) && function() {
       
   343 				var result,
       
   344 					uid = +new Date();
       
   345 				try {
       
   346 					self.storage.setItem(uid, uid);
       
   347 					result = parseInt(self.storage.getItem(uid)) === uid;
       
   348 					self.storage.removeItem(uid);
       
   349 					return result;
       
   350 				} catch (e) {
       
   351 				}
       
   352 			}();
       
   353 			if (use_storage) {
       
   354 				self.settingsKey = "AMS_settings_" + location.pathname + location.hash + "_" + self.gridId;
       
   355 				self.settings = self.storage.getItem(self.settingsKey);
       
   356 				self.positionKey = "AMS_position_" + location.pathname + location.hash + "_" + self.gridId;
       
   357 				self.position = self.storage.getItem(self.positionKey);
       
   358 			}
       
   359 			if (("ontouchstart" in globals) ||
       
   360 				globals.DocumentTouch && globals.document instanceof globals.DocumentTouch) {
       
   361 				self.clickEvent = "touchstart";
       
   362 			} else {
       
   363 				self.clickEvent = "click";
       
   364 			}
       
   365 		},
       
   366 
       
   367 		_runLoaderWidget: function(widget) {
       
   368 			var self = this;
       
   369 			if (self.options.indicator) {
       
   370 				widget.find('.ams-widget-loader')
       
   371 					.stop(true, true)
       
   372 					.fadeIn(100)
       
   373 					.delay(self.options.indicatorTime)
       
   374 					.fadeOut(100);
       
   375 			}
       
   376 		},
       
   377 
       
   378 		_loadAjaxFile: function(url, widget, loader) {
       
   379 			ams.skin && ams.skin.loadURL(url, widget.find('.widget-body'));
       
   380 		},
       
   381 
       
   382 		_saveWidgetSettings: function() {
       
   383 			var self = this;
       
   384 			self._getSettings();
       
   385 			if (self.storage) {
       
   386 				var gridSettings = [];
       
   387 				self.grid.find(self.options.widgets).each(function() {
       
   388 					var widget = $(this);
       
   389 					var widgetSettings = {};
       
   390 					widgetSettings.id = widget.attr('id');
       
   391 					widgetSettings.style = widget.attr('data-widget-attstyle');
       
   392 					widgetSettings.title = widget.children('header').children('h2').text();
       
   393 					widgetSettings.hidden = widget.is(':hidden') ? 1 : 0;
       
   394 					widgetSettings.collapsed = widget.hasClass('ams-widget-collapsed') ? 1 : 0;
       
   395 					gridSettings.push(widgetSettings);
       
   396 				});
       
   397 				var gridSettingsStr = JSON.stringify({widget: gridSettings});
       
   398 				if (self.settings !== gridSettingsStr) {
       
   399 					self.storage.setItem(self.settingsKey, gridSettingsStr);
       
   400 				}
       
   401 				if (typeof (self.options.onSave) === 'function') {
       
   402 					self.options.onSave.call(this, null, gridSettings);
       
   403 				}
       
   404 			}
       
   405 		},
       
   406 
       
   407 		_saveWidgetPosition: function() {
       
   408 			var self = this;
       
   409 			self._getSettings();
       
   410 			if (self.storage) {
       
   411 				var gridPosition = [];
       
   412 				self.grid.find(self.options.subgrid + ".sortable-grid").each(function() {
       
   413 					var subgridPosition = [];
       
   414 					$(this).children(self.options.widgets).each(function() {
       
   415 						var subObj = {};
       
   416 						subObj.id = $(this).attr("id");
       
   417 						subgridPosition.push(subObj);
       
   418 					});
       
   419 					var out = {section: subgridPosition};
       
   420 					gridPosition.push(out);
       
   421 				});
       
   422 				var gridPositionStr = JSON.stringify({grid: gridPosition});
       
   423 				if (self.position !== gridPositionStr) {
       
   424 					self.storage.setItem(self.positionKey, gridPositionStr);
       
   425 				}
       
   426 				if (typeof (self.options.onSave) === 'function') {
       
   427 					self.options.onSave.call(this, null, gridPosition);
       
   428 				}
       
   429 			}
       
   430 		},
       
   431 
       
   432 		_setClickEvents: function() {
       
   433 
       
   434 			function setFullscreenHeight() {
       
   435 				var mode = $('#ams-widget-fullscreen-mode');
       
   436 				if (mode.length > 0) {
       
   437 					var widgets = mode.find(self.options.widgets);
       
   438 					var windowHeight = $(window).height();
       
   439 					var headerHeight = widgets.children('header')
       
   440 						.height();
       
   441 					widgets.children('div')
       
   442 						.height(windowHeight - headerHeight - 15);
       
   443 				}
       
   444 			}
       
   445 
       
   446 			var self = this;
       
   447 			self._getSettings();
       
   448 
       
   449 			// Toggle button
       
   450 			self.widget.on(self.clickEvent, '.ams-widget-toggle-btn', function(e) {
       
   451 				e.preventDefault();
       
   452 				var button = $(this);
       
   453 				var widget = button.parents(self.options.widgets).first();
       
   454 				var widgetOptions = widget.data('widget-options');
       
   455 				var toggleClass = widgetOptions.toggleClass.split('|');
       
   456 				self._runLoaderWidget(widget);
       
   457 				var canToggle = true;
       
   458 				if (widget.hasClass('ams-widget-collapsed')) {
       
   459 					if (widgetOptions.onToggle) {
       
   460 						canToggle = widgetOptions.onToggle.call(this, widget, 'expand');
       
   461 					}
       
   462 					if (canToggle !== false) {
       
   463 						button.children().removeClass(toggleClass[1])
       
   464 							.addClass(toggleClass[0]);
       
   465 						widget.removeClass('ams-widget-collapsed')
       
   466 							.children('[role=content]').slideDown(widgetOptions.toggleSpeed, function() {
       
   467 							self._saveWidgetSettings();
       
   468 						});
       
   469 					}
       
   470 				} else {
       
   471 					if (widgetOptions.onToggle) {
       
   472 						canToggle = widgetOptions.onToggle.call(this, widget, 'collapse');
       
   473 					}
       
   474 					if (canToggle !== false) {
       
   475 						button.children().removeClass(toggleClass[0])
       
   476 							.addClass(toggleClass[1]);
       
   477 						widget.addClass('ams-widget-collapsed')
       
   478 							.children('[role=content]').slideUp(widgetOptions.toggleSpeed, function() {
       
   479 							self._saveWidgetSettings();
       
   480 						});
       
   481 					}
       
   482 				}
       
   483 			});
       
   484 			self.widget.on('dblclick', 'header', function(e) {
       
   485 				$('.ams-widget-toggle-btn', this).click();
       
   486 			});
       
   487 
       
   488 			// Fullscreen button
       
   489 			self.widget.on(self.clickEvent, '.ams-widget-fullscreen-btn', function(e) {
       
   490 				e.preventDefault();
       
   491 				var button = $(this);
       
   492 				var widget = button.parents(self.options.widgets);
       
   493 				var widgetOptions = widget.data('widget-options');
       
   494 				var fullscreenClass = widgetOptions.fullscreenClass.split('|');
       
   495 				var content = widget.children('div');
       
   496 				self._runLoaderWidget(widget);
       
   497 				if ($('#ams-widget-fullscreen-mode').length > 0) {
       
   498 					$('.nooverflow').removeClass('nooverflow');
       
   499 					widget.unwrap('<div>')
       
   500 						.children('div')
       
   501 						.removeAttr('style')
       
   502 						.end()
       
   503 						.find('.ams-widget-fullscreen-btn')
       
   504 						.children()
       
   505 						.removeClass(fullscreenClass[1])
       
   506 						.addClass(fullscreenClass[0])
       
   507 						.parents(self.controls)
       
   508 						.children('a')
       
   509 						.show();
       
   510 					if (content.hasClass('ams-widget-visible')) {
       
   511 						content.hide()
       
   512 							.removeClass('ams-widget-visible');
       
   513 					}
       
   514 				} else {
       
   515 					$('body').addClass('nooverflow');
       
   516 					widget.wrap('<div id="ams-widget-fullscreen-mode"></div>')
       
   517 						.parent()
       
   518 						.find('.ams-widget-fullscreen-btn')
       
   519 						.children()
       
   520 						.removeClass(fullscreenClass[0])
       
   521 						.addClass(fullscreenClass[1])
       
   522 						.parents(self.controls)
       
   523 						.children('a:not(.ams-widget-fullscreen-btn)')
       
   524 						.hide();
       
   525 					if (content.is(':hidden')) {
       
   526 						content.show()
       
   527 							.addClass('ams-widget-visible');
       
   528 					}
       
   529 				}
       
   530 				setFullscreenHeight();
       
   531 				if (typeof (widgetOptions.onFullscreen) === 'function') {
       
   532 					widgetOptions.onFullscreen.call(this, widget);
       
   533 				}
       
   534 			});
       
   535 			$(window).resize(function() {
       
   536 				setFullscreenHeight();
       
   537 			});
       
   538 
       
   539 			// Edit button
       
   540 			self.widget.on(self.clickEvent, '.ams-widget-edit-btn', function(e) {
       
   541 				e.preventDefault();
       
   542 				var button = $(this);
       
   543 				var widget = button.parents(self.options.widgets);
       
   544 				var widgetOptions = widget.data('widget-options');
       
   545 				var editClass = widgetOptions.editClass.split('|');
       
   546 				self._runLoaderWidget(widget);
       
   547 				var placeholder = widget.find(widgetOptions.editPlaceholder);
       
   548 				if (placeholder.is(':visible')) {
       
   549 					button.children()
       
   550 						.removeClass(editClass[1])
       
   551 						.addClass(editClass[0]);
       
   552 					placeholder.slideUp(widgetOptions.editSpeed, function() {
       
   553 						self._saveWidgetSettings();
       
   554 					});
       
   555 				} else {
       
   556 					button.children()
       
   557 						.removeClass(editClass[0])
       
   558 						.addClass(editClass[1]);
       
   559 					placeholder.slideDown(widgetOptions.editSpeed);
       
   560 				}
       
   561 				if (typeof (widgetOptions.onEdit) === 'function') {
       
   562 					widgetOptions.onEdit.call(this, widget);
       
   563 				}
       
   564 			});
       
   565 			$(self.options.editPlaceholder).find('input').keyup(function() {
       
   566 				$(this).parents(self.options.widgets)
       
   567 					.children('header')
       
   568 					.children('h2')
       
   569 					.text($(this).val());
       
   570 			});
       
   571 
       
   572 			// Custom button
       
   573 			self.widget.on(self.clickEvent, '.ams-widget-custom-btn', function(e) {
       
   574 				e.preventDefault();
       
   575 				var button = $(this);
       
   576 				var widget = button.parents(self.options.widgets);
       
   577 				var widgetOptions = widget.data('widget-options');
       
   578 				var customClass = widgetOptions.customClass.split('|');
       
   579 				self._runLoaderWidget(widget);
       
   580 				if (button.children('.' + customClass[0]).length > 0) {
       
   581 					button.children()
       
   582 						.removeClass(customClass[0])
       
   583 						.addClass(customClass[1]);
       
   584 					if (typeof (widgetOptions.customStart) === 'function') {
       
   585 						widgetOptions.customStart.call(this, widget);
       
   586 					}
       
   587 				} else {
       
   588 					button.children('.' + customClass[1])
       
   589 						.addClass(customClass[0]);
       
   590 					if (typeof (widgetOptions.customEnd) === 'function') {
       
   591 						widgetOptions.customEnd.call(this, widget);
       
   592 					}
       
   593 				}
       
   594 				self._saveWidgetSettings();
       
   595 			});
       
   596 
       
   597 			// Delete button
       
   598 			self.widget.on(self.clickEvent, '.ams-widget-delete-btn', function(e) {
       
   599 				e.preventDefault();
       
   600 				var button = $(this);
       
   601 				var widget = button.parents(self.options.widgets);
       
   602 				var widgetOptions = widget.data('widget-options');
       
   603 				var wId = widget.attr('id');
       
   604 				var title = widget.children('header').children('h2').text();
       
   605 				ams.ajax && ams.ajax.check(MyAMS.notify,
       
   606 										   ams.baseURL + 'myams-notify' + (ams.devmode ? '.js' : '.min.js'),
       
   607 										   function() {
       
   608 											   ams.notify.messageBox({
       
   609 																		 title: '<i class="fa fa-times" style="color: #ed1c24;"></i> ' + widgetOptions.deleteLabel + ' "' + title + '"',
       
   610 																		 content: MyAMSWidget.i18n.DELETE_MSG,
       
   611 																		 buttons: "[" + ams.i18n.BTN_OK + "][" + ams.i18n.BTN_CANCEL + "]"
       
   612 																	 }, function(buttonPressed) {
       
   613 												   if (buttonPressed === ams.i18n.BTN_OK) {
       
   614 													   self._runLoaderWidget(widget);
       
   615 													   $('#' + wId).fadeOut(widgetOptions.deleteSpeed, function() {
       
   616 														   button.remove();
       
   617 														   if (typeof (widgetOptions.onDelete) === 'function') {
       
   618 															   widgetOptions.onDelete.call(this, widget);
       
   619 														   }
       
   620 													   });
       
   621 												   }
       
   622 											   });
       
   623 										   });
       
   624 			});
       
   625 
       
   626 			// Refresh button
       
   627 			self.widget.on(self.clickEvent, '.ams-widget-refresh-btn', function(e) {
       
   628 				e.preventDefault();
       
   629 				var button = $(this);
       
   630 				var widget = button.parents(self.options.widgets);
       
   631 				var path = widget.data('widget-load');
       
   632 				var loader = widget.children();
       
   633 				button.button('loading');
       
   634 				loader.addClass('widget-body-ajax-loading');
       
   635 				setTimeout(function() {
       
   636 					button.button('reset');
       
   637 					loader.removeClass('widget-body-ajax-loading');
       
   638 					self._loadAjaxFile(widget, path, loader);
       
   639 				}, 1000);
       
   640 			});
       
   641 		}
       
   642 	};
       
   643 
       
   644 
       
   645 	var MyAMSWidget = {
       
   646 
       
   647 		i18n: $.extend({
       
   648 						   SETTINGS_KEY_LABEL: "Reset settings?",
       
   649 						   POSITION_KEY_LABEL: "Reset position?",
       
   650 						   TIMESTAMP_FORMAT: "Last update: %d%/%m%/%y% %h%:%i%:%s",
       
   651 						   ERROR_LABEL: "An error occured: ",
       
   652 						   UPDATED_LABEL: "Last update: ",
       
   653 						   REFRESH_LABEL: "Refresh",
       
   654 						   EDIT_BTN: "Edit title",
       
   655 						   DELETE_BTN: "Delete",
       
   656 						   DELETE_LABEL: "Remove component: ",
       
   657 						   DELETE_MSG: "WARNING: this action can't be undone!",
       
   658 						   FULLSCREEN_BTN: "Fullscreen",
       
   659 						   COLLAPSE_BTN: "Collapse",
       
   660 						   REFRESH_BTN: "Reload content",
       
   661 						   LOADING_MSG: "Loading..."
       
   662 					   }, ams.plugins.i18n.widgets),
       
   663 
       
   664 		initWidgetsGrid: function(grid) {
       
   665 			if (!grid.exists()) {
       
   666 				return;
       
   667 			}
       
   668 			var options = $('.ams-widget:first', grid).data('AMSWidget').options;
       
   669 			if (options.sortable && $.ui) {
       
   670 				var sortItem = grid.find('.sortable-grid').not("[data-widget-excludegrid]");
       
   671 				sortItem.sortable({
       
   672 									  items: sortItem.find('.ams-widget-sortable'),
       
   673 									  connectWith: sortItem,
       
   674 									  placeholder: options.placeholderClass,
       
   675 									  cursor: 'move',
       
   676 									  revert: true,
       
   677 									  opacity: options.opacity,
       
   678 									  delay: 200,
       
   679 									  cancel: '.button-icon, #ams-widget-fullscreen-mode >div',
       
   680 									  zIndex: 10000,
       
   681 									  handle: options.dragHandle,
       
   682 									  forcePlaceholderSize: true,
       
   683 									  forceHelperSize: true,
       
   684 									  update: function(event, ui) {
       
   685 										  var widget = ui.item.data('AMSWidget');
       
   686 										  widget._runLoaderWidget(widget.widget);
       
   687 										  widget._saveWidgetPosition();
       
   688 										  if (typeof (options.onChange) === 'function') {
       
   689 											  options.onChange.call(this, ui.item);
       
   690 										  }
       
   691 									  }
       
   692 								  });
       
   693 			}
       
   694 		}
       
   695 	};
       
   696 
       
   697 	MyAMSWidget.defaults = {
       
   698 		grid: '.ams-widget-grid',
       
   699 		subgrid: 'section',
       
   700 		widgets: '.ams-widget',
       
   701 		controls: '.ams-widget-ctrls',
       
   702 		storage: 'local',
       
   703 		deleteSettingsKey: '',
       
   704 		settingsKeyLabel: MyAMSWidget.i18n.SETTINGS_KEY_LABEL,
       
   705 		deletePositionKey: '',
       
   706 		positionKeyLabel: MyAMSWidget.i18n.POSITION_KEY_LABEL,
       
   707 		sortable: false,
       
   708 		hiddenButtons: false,
       
   709 		// Toggle button
       
   710 		toggleButton: false,
       
   711 		toggleClass: 'fa fa-minus|fa fa-plus',
       
   712 		toggleSpeed: 200,
       
   713 		onToggle: null,
       
   714 		// Delete button
       
   715 		deleteButton: false,
       
   716 		deleteClass: 'fa fa-times',
       
   717 		deleteSpeed: 200,
       
   718 		onDelete: null,
       
   719 		// Edit button
       
   720 		editButton: false,
       
   721 		editPlaceholder: '.ams-widget-editbox',
       
   722 		editClass: 'fa fa-cog|fa fa-save',
       
   723 		editSpeed: 200,
       
   724 		onEdit: null,
       
   725 		// Fullscreen button
       
   726 		fullscreenButton: false,
       
   727 		fullscreenClass: 'fa fa-expand|fa fa-compress',
       
   728 		fullscreenDiff: 3,
       
   729 		onFullscreen: null,
       
   730 		// Custom button
       
   731 		customButton: false,
       
   732 		customClass: 'folder-10|next-10',
       
   733 		customStart: null,
       
   734 		customEnd: null,
       
   735 		// Buttons order
       
   736 		buttonsOrder: '%refresh% %custom% %edit% %toggle% %fullscreen% %delete%',
       
   737 		opacity: 1.0,
       
   738 		dragHandle: '> header',
       
   739 		placeholderClass: 'ams-widget-placeholder',
       
   740 		indicator: true,
       
   741 		indicatorTime: 600,
       
   742 		ajax: true,
       
   743 		timestampPlaceholder: '.ams-widget-timestamp',
       
   744 		timestampFormat: MyAMSWidget.i18n.TIMESTAMP_FORMAT,
       
   745 		refreshButton: true,
       
   746 		refreshButtonClass: 'fa fa-refresh',
       
   747 		errorLabel: MyAMSWidget.i18n.ERROR_LABEL,
       
   748 		updatedLabel: MyAMSWidget.i18n.UPDATED_LABEL,
       
   749 		refreshLabel: MyAMSWidget.i18n.REFRESH_LABEL,
       
   750 		deleteLabel: MyAMSWidget.i18n.DELETE_LABEL,
       
   751 		afterLoad: null,
       
   752 		rtl: false,
       
   753 		onChange: null,
       
   754 		onSave: null,
       
   755 		ajax_nav: ams.ajax_nav
       
   756 	};
       
   757 
       
   758 	globals.MyAMSWidget = MyAMSWidget;
       
   759 
       
   760 
       
   761 	$.fn.extend({
       
   762 
       
   763 					MyAMSWidget: function(options) {
       
   764 						return this.each(function() {
       
   765 							var widget = $(this);
       
   766 							var data = widget.data('AMSWidget');
       
   767 							if (!data) {
       
   768 								var grid = widget.parents(options.grid || MyAMSWidget.defaults.grid);
       
   769 								var grid_options = {};
       
   770 								if (grid.exists()) {
       
   771 									var grid_data = grid.data();
       
   772 									grid_options = {
       
   773 										grid: grid_data.amsWidgetGrid,
       
   774 										subgrid: grid_data.amsWidgetSubgrid,
       
   775 										controls: grid_data.amsWidgetControls,
       
   776 										storage: grid_data.amsWidgetStorage,
       
   777 										deleteSettingsKey: grid_data.amsWidgetDeleteSettingsKey,
       
   778 										deletePositionKey: grid_data.amsWidgetDeletePositionKey,
       
   779 										sortable: grid_data.amsWidgetSortable,
       
   780 										hiddenButtons: grid_data.amsWidgetHiddenButtons,
       
   781 										toggleButton: grid_data.amsWidgetToggleButton,
       
   782 										toggleClass: grid_data.amsWidgetToggleClass,
       
   783 										onToggle: ams.getFunctionByName(grid_data.amsWidgetToggleCallback),
       
   784 										deleteButton: grid_data.amsWidgetDeleteButton,
       
   785 										deleteClass: grid_data.amsWidgetDeleteClass,
       
   786 										onDelete: ams.getFunctionByName(grid_data.amsWidgetDeleteCallback),
       
   787 										editButton: grid_data.amsWidgetEditButton,
       
   788 										editPlaceholder: grid_data.amsWidgetEditPlaceholder,
       
   789 										editClass: grid_data.amsWidgetEditClass,
       
   790 										onEdit: ams.getFunctionByName(grid_data.amsWidgetEditCallback),
       
   791 										fullscreenButton: grid_data.amsWidgetFullscreenButton,
       
   792 										fullscreenClass: grid_data.amsWidgetFullscreenClass,
       
   793 										fullscreenDiff: grid_data.amsWidgetFullscreenDiff,
       
   794 										onFullscreen: ams.getFunctionByName(grid_data.amsWidgetFullscreenCallback),
       
   795 										customButton: grid_data.amsWidgetCustomButton,
       
   796 										customClass: grid_data.amsWidgetCustomClass,
       
   797 										customStart: ams.getFunctionByName(grid_data.amsWidgetCustomStartCallback),
       
   798 										customEnd: ams.getFunctionByName(grid_data.amsWidgetCustomStartCallback),
       
   799 										buttonsOrder: grid_data.amsWidgetButtonsOrder,
       
   800 										opacity: grid_data.amsWidgetOpacity,
       
   801 										dragHandle: grid_data.amsWidgetDragHandle,
       
   802 										placeholderClass: grid_data.amsWidgetPlaceholderClass,
       
   803 										indicator: grid_data.amsWidgetIndicator,
       
   804 										indicatorTime: grid_data.amsWidgetIndicatorTime,
       
   805 										ajax: grid_data.amsWidgetAjax,
       
   806 										timestampPlaceholder: grid_data.amsWidgetTimestampPlaceholder,
       
   807 										timestampFormat: grid_data.amsWidgetTimestampFormat,
       
   808 										refreshButton: grid_data.amsWidgetRefreshButton,
       
   809 										refreshClass: grid_data.amsWidgetRefreshClass,
       
   810 										errorLabel: grid_data.amsWidgetErrorLabel,
       
   811 										updatedLabel: grid_data.amsWidgetUpdatedLabel,
       
   812 										refreshLabel: grid_data.amsWidgetRefreshLabel,
       
   813 										deleteLabel: grid_data.amsWidgetDeleteLabel,
       
   814 										afterLoad: ams.getFunctionByName(grid_data.amsWidgetAfterLoadCallback),
       
   815 										rtl: grid_data.amsWidgetRtl,
       
   816 										onChange: ams.getFunctionByName(grid_data.amsWidgetChangeCallback),
       
   817 										onSave: ams.getFunctionByName(grid_data.amsWidgetSaveCallback),
       
   818 										ajax_nav: ams.ajax_nav
       
   819 									};
       
   820 								}
       
   821 								var settings = $.fn.extend({}, grid_options, widget.data('ams-widget-options') || {}, options);
       
   822 								widget.data('AMSWidget', new Widget(widget, settings));
       
   823 							}
       
   824 						});
       
   825 					}
       
   826 
       
   827 				});
       
   828 
       
   829 })(jQuery, this);