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