Files
pathfinder/js/app/util.js
2017-07-14 23:49:32 +02:00

2200 lines
68 KiB
JavaScript

/**
* Util
*/
define([
'jquery',
'app/init',
'config/system_effect',
'config/signature_type',
'bootbox',
'localForage',
'velocity',
'velocityUI',
'customScrollbar',
'validator',
'easyPieChart',
'hoverIntent',
'bootstrapConfirmation',
'bootstrapToggle'
], function($, Init, SystemEffect, SignatureType, bootbox, localforage) {
'use strict';
let config = {
ajaxOverlayClass: 'pf-loading-overlay',
ajaxOverlayWrapperClass: 'pf-loading-overlay-wrapper',
// form
formEditableFieldClass: 'pf-editable', // class for all xEditable fields
formErrorContainerClass: 'pf-dialog-error-container', // class for "error" containers in dialogs
formWarningContainerClass: 'pf-dialog-warning-container', // class for "warning" containers in dialogs
formInfoContainerClass: 'pf-dialog-info-container', // class for "info" containers in dialogs
// head
headMapTrackingId: 'pf-head-map-tracking', // id for "map tracking" toggle (checkbox)
headCharacterSwitchId: 'pf-head-character-switch', // id for "character switch" popover
headCurrentLocationId: 'pf-head-current-location', // id for "show current location" element
// menu
menuButtonFullScreenId: 'pf-menu-button-fullscreen', // id for menu button "fullscreen"
menuButtonMagnetizerId: 'pf-menu-button-magnetizer', // id for menu button "magnetizer"
menuButtonGridId: 'pf-menu-button-grid', // id for menu button "grid snap"
menuButtonEndpointId: 'pf-menu-button-endpoint', // id for menu button "endpoint" overlays
settingsMessageVelocityOptions: {
duration: 180
},
// dialogs
dialogClass: 'modal-dialog', // class for all dialogs (bootstrap)
// map module
mapModuleId: 'pf-map-module', // id for main map module
mapTabBarId: 'pf-map-tabs', // id for map tab bar
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
mapClass: 'pf-map' , // class for all maps
// animation
animationPulseSuccessClass: 'pf-animation-pulse-success', // animation class
animationPulseWarningClass: 'pf-animation-pulse-warning', // animation class
// popover
popoverTriggerClass: 'pf-popover-trigger' // class for "popover" trigger elements
};
let stopTimerCache = {}; // cache for stopwatch timer
let animationTimerCache = {}; // cache for table row animation timeout
let localStorage; // cache for "localForage" singleton
/*
* ===========================================================================================================
* Global jQuery plugins for some common and frequently used functions
* ==========================================================================================================
*/
/**
* displays a loading indicator on an element
*/
$.fn.showLoadingAnimation = function(options){
return this.each(function(){
let loadingElement = $(this);
let iconSize = 'fa-lg';
// disable all events
loadingElement.css('pointer-events', 'none');
if(options){
if(options.icon){
if(options.icon.size){
iconSize = options.icon.size;
}
}
}
let overlay = $('<div>', {
class: config.ajaxOverlayClass
}).append(
$('<div>', {
class: [config.ajaxOverlayWrapperClass].join(' ')
}).append(
$('<i>', {
class: ['fa', 'fa-fw', iconSize, 'fa-refresh', 'fa-spin'].join(' ')
})
)
);
loadingElement.append(overlay);
// fade in
$(overlay).velocity({
opacity: 0.6
},{
duration: 120
});
});
};
/**
* removes a loading indicator
*/
$.fn.hideLoadingAnimation = function(){
return this.each(function(){
let loadingElement = $(this);
let overlay = loadingElement.find('.' + config.ajaxOverlayClass );
if(overlay.length){
// important: "stop" is required to stop "show" animation
// -> otherwise "complete" callback is not fired!
overlay.velocity('stop').velocity('reverse', {
complete: function(){
$(this).remove();
// enable all events
loadingElement.css('pointer-events', 'auto');
}
});
}
});
};
/**
* show "splash" loading overlay
* @param callback
*/
$.fn.showSplashOverlay = function(callback){
let splashOverlay = $(this);
splashOverlay.velocity('fadeIn', {
duration: Init.animationSpeed.splashOverlay,
complete: function(){
// execute callback function if given
if(callback !== undefined){
callback();
}
}
});
};
/**
* hide "splash" loading overlay
*/
$.fn.hideSplashOverlay = function(){
let splashOverlay = $(this);
splashOverlay.velocity('fadeOut', {
duration: Init.animationSpeed.splashOverlay
});
};
/**
* show a unique generated captcha image
* @param reason
* @param callback
* @returns {*}
*/
$.fn.showCaptchaImage = function(reason, callback){
return this.each(function(){
let captchaWrapper = $(this);
let captchaImage = captchaWrapper.find('img');
captchaWrapper.showLoadingAnimation(config.loadingOptions);
getCaptchaImage(reason, function(base64Image){
captchaImage.attr('src', base64Image).show();
captchaWrapper.hideLoadingAnimation({
icon: {
size: 'fa-2x'
}
});
if(callback){
callback();
}
});
});
};
/**
* request a captcha image
* @param reason
* @param callback
*/
let getCaptchaImage = function(reason, callback){
$.ajax({
type: 'POST',
url: Init.path.getCaptcha,
data: {
reason: reason
},
dataType: 'json'
}).done(function(responseData){
if(responseData.error.length > 0){
showNotify({title: 'getCaptchaImage', text: 'Captcha image gneration failed', type: 'error'});
}else{
callback(responseData.img);
}
}).fail(function( jqXHR, status, error) {
let reason = status + ' ' + error;
showNotify({title: jqXHR.status + ': getCaptchaImage', text: reason, type: 'error'});
});
};
/**
* reset/clear form fields
* @returns {*}
*/
$.fn.resetFormFields = function(){
return this.each(function(){
let field = $(this);
if( !field.is('select') ){
// "input"
field.val('');
}
field.parents('.form-group').removeClass('has-error has-success');
});
};
/**
* show form messages
* check: showMessage() for en other way of showing messages
* @param errors
*/
$.fn.showFormMessage = function(errors){
let formElement = $(this);
let errorMessage = [];
let warningMessage = [];
let infoMessage = [];
for(let i = 0; i < errors.length; i++){
if(errors[i].type === 'error'){
errorMessage.push( errors[i].message );
// mark form field as invalid in case of a validation error
if(
errors[i].field &&
errors[i].field.length > 0
){
let formField = formElement.find('[name="' + errors[i].field + '"]');
formField.parents('.form-group').removeClass('has-success').addClass('has-error');
}
}else if(errors[i].type === 'warning'){
warningMessage.push( errors[i].message );
}else if(errors[i].type === 'info'){
infoMessage.push( errors[i].message );
}
}
if(errorMessage.length > 0){
formElement.hideFormMessage('error', function(element){
$(element).find('small').html( errorMessage.join('<br>') );
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
});
}
if(warningMessage.length > 0){
formElement.hideFormMessage('warning', function(element){
$(element).find('small').html( warningMessage.join('<br>') );
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
});
}
if(infoMessage.length > 0){
formElement.hideFormMessage('info', function(element){
$(element).find('small').html( infoMessage.join('<br>') );
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
});
}
};
/**
* hide all form messages
* @param type
* @param callback
*/
$.fn.hideFormMessage = function(type, callback){
let formElement = $(this);
let settingsMessageVelocityOptions = $.extend({}, config.settingsMessageVelocityOptions);
// check if callback exists
if(callback !== undefined){
settingsMessageVelocityOptions.complete = callback;
// new error will be shown afterwards -> keep display
settingsMessageVelocityOptions.display = 'block';
}
let messageElement = null;
switch(type){
case 'error':
// find error container
messageElement = formElement.find('.' + config.formErrorContainerClass);
break;
case 'warning':
messageElement = formElement.find('.' + config.formWarningContainerClass);
break;
case 'info':
messageElement = formElement.find('.' + config.formInfoContainerClass);
break;
case 'all':
messageElement = formElement.find(
'.' + config.formErrorContainerClass + ', ' +
'.' + config.formWarningContainerClass + ', ' +
'.' + config.formInfoContainerClass
);
}
if(messageElement){
if(messageElement.is(':visible')){
messageElement.velocity('transition.slideDownOut', settingsMessageVelocityOptions);
}else if(callback){
// skip hide animation
callback(messageElement);
}
}
};
/**
* init form elements for validation (bootstrap3 validation)
* @param options
* @returns {*}
*/
$.fn.initFormValidation = function(options){
options = (typeof options === 'undefined')? {} : options;
return this.each(function(){
let form = $(this);
// init form validation
form.validator(options);
// validation event listener
form.on('valid.bs.validator', function(validatorObj){
let inputGroup = $(validatorObj.relatedTarget).parents('.form-group');
if(inputGroup){
inputGroup.removeClass('has-error').addClass('has-success');
}
});
form.on('invalid.bs.validator', function(validatorObj){
let field = $(validatorObj.relatedTarget);
let inputGroup = field.parents('.form-group');
if(inputGroup){
inputGroup.removeClass('has-success').addClass('has-error');
}
});
});
};
/**
* checks whether a bootstrap form is valid or not
* validation plugin does not provide a proper function for this
* @returns {boolean}
*/
$.fn.isValidForm = function(){
let form = $(this);
let valid = false;
let errorElements = form.find('.has-error');
if(errorElements.length === 0){
valid = true;
}
return valid;
};
/**
* check multiple element if they arecurrently visible in viewport
* @returns {Array}
*/
$.fn.isInViewport = function(){
let visibleElement = [];
this.each(function(){
let element = $(this)[0];
let top = element.offsetTop;
let left = element.offsetLeft;
let width = element.offsetWidth;
let height = element.offsetHeight;
while(element.offsetParent) {
element = element.offsetParent;
top += element.offsetTop;
left += element.offsetLeft;
}
if(
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
){
visibleElement.push( this );
}
});
return visibleElement;
};
/**
* init the map-update-counter as "easy-pie-chart"
*/
$.fn.initMapUpdateCounter = function(){
let counterChart = $(this);
counterChart.easyPieChart({
barColor: function(percent){
let color = '#568a89';
if(percent <= 30){
color = '#d9534f';
}else if(percent <= 50){
color = '#f0ad4e';
}
return color;
},
trackColor: '#2b2b2b',
size: 30,
scaleColor: false,
lineWidth: 2,
animate: 1000
});
};
/**
* init tooltips on an element
* @param {object} options
* @returns {*}
*/
$.fn.initTooltips = function(options){
options = (typeof options === 'object') ? options : {};
let defaultOptions = {
container: this,
delay: 100
};
options = $.extend(defaultOptions, options);
return this.each(function(){
let tooltipElements = $(this).find('[title]');
tooltipElements.tooltip('destroy').tooltip(options);
});
};
/**
* adds a popup tooltip with character information (created/updated)
* @param tooltipData
*/
$.fn.addCharacterInfoTooltip = function(tooltipData){
let element = $(this);
if(
tooltipData.created.character &&
tooltipData.updated.character
){
let createdData = tooltipData.created;
let updatedData = tooltipData.updated;
// check if data has changed
if(
element.data('created') !== createdData.created ||
element.data('updated') !== updatedData.updated
){
// data changed
// set new data for next check
element.data('created', createdData.created);
element.data('updated', updatedData.updated);
let statusCreatedClass = getStatusInfoForCharacter(createdData.character, 'class');
let statusUpdatedClass = getStatusInfoForCharacter(updatedData.character, 'class');
// convert timestamps
let dateCreated = new Date(createdData.created * 1000);
let dateUpdated = new Date(updatedData.updated * 1000);
let dateCreatedUTC = convertDateToUTC(dateCreated);
let dateUpdatedUTC = convertDateToUTC(dateUpdated);
let data = {
created: createdData,
updated: updatedData,
createdTime: convertDateToString(dateCreatedUTC),
updatedTime: convertDateToString(dateUpdatedUTC),
createdStatusClass: statusCreatedClass,
updatedStatusClass: statusUpdatedClass
};
requirejs(['text!templates/tooltip/character_info.html', 'mustache'], function(template, Mustache) {
let content = Mustache.render(template, data);
element.popover({
placement: 'top',
html: true,
trigger: 'hover',
content: '',
container: 'body',
title: 'Created / Updated',
delay: {
show: 250,
hide: 0
}
});
// set new popover content
let popover = element.data('bs.popover');
popover.options.content = content;
});
}
}
};
/**
* add character switch popover
* @param userData
*/
$.fn.initCharacterSwitchPopover = function(userData){
let elements = $(this);
let eventNamespace = 'hideCharacterPopup';
requirejs(['text!templates/tooltip/character_switch.html', 'mustache'], function (template, Mustache) {
let data = {
id: config.headCharacterSwitchId,
routes: Init.routes,
userData: userData,
otherCharacters: $.grep( userData.characters, function( character ) {
// exclude current active character
return character.id !== userData.character.id;
})
};
let content = Mustache.render(template, data);
return elements.each(function() {
let element = $(this);
// check if tooltip already exists -> remove it
if(element.data('bs.popover') !== undefined){
element.off('click').popover('destroy');
}
element.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
let easeEffect = $(this).attr('data-easein');
let popoverData = $(this).data('bs.popover');
let popoverElement = null;
let velocityOptions = {
duration: Init.animationSpeed.dialogEvents
};
if(popoverData === undefined){
// init popover and add specific class to it (for styling)
$(this).popover({
html: true,
title: 'select character',
trigger: 'manual',
placement: 'bottom',
container: 'body',
content: content,
animation: false
}).data('bs.popover').tip().addClass('pf-popover');
$(this).popover('show');
popoverElement = $(this).data('bs.popover').tip();
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
popoverElement.initTooltips();
}else{
popoverElement = $(this).data('bs.popover').tip();
if(popoverElement.is(':visible')){
popoverElement.velocity('reverse');
}else{
$(this).popover('show');
popoverElement.initTooltips();
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
}
}
});
// set popup "close" observer
elements.initPopoverClose(eventNamespace);
});
});
};
/**
* set "popover" close action on clicking "somewhere" on the <body>
* @param eventNamespace
* @returns {*}
*/
$.fn.initPopoverClose = function(eventNamespace){
return this.each(function() {
$('body').off('click.' + eventNamespace).on('click.' + eventNamespace + ' contextmenu', function (e) {
$('.' + config.popoverTriggerClass).each(function () {
let popoverElement = $(this);
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if(
!popoverElement.is(e.target) &&
popoverElement.has(e.target).length === 0 &&
$('.popover').has(e.target).length === 0
){
let popover = popoverElement.data('bs.popover');
if(
popover !== undefined &&
popover.tip().is(':visible')
){
popoverElement.popover('hide');
}
}
});
});
});
};
/**
* add a wormhole tooltip with wh specific data to elements
* @param tooltipData
* @returns {*}
*/
$.fn.addWormholeInfoTooltip = function(tooltipData){
return this.each(function() {
let element = $(this);
requirejs(['text!templates/tooltip/wormhole_info.html', 'mustache'], function (template, Mustache) {
let content = Mustache.render(template, tooltipData);
element.popover({
placement: 'top',
html: true,
trigger: 'hover',
content: '',
container: 'body',
title: tooltipData.name +
'<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>',
delay: {
show: 250,
hide: 0
}
});
// set new popover content
let popover = element.data('bs.popover');
popover.options.content = content;
});
});
};
/**
* display a custom message (info/warning/error) to a container element
* check: $.fn.showFormMessage() for an other way of showing messages
* @param config
*/
$.fn.showMessage = function(config){
let containerElement = $(this);
requirejs(['text!templates/form/message.html', 'mustache'], function(template, Mustache) {
let messageTypeClass = 'alert-danger';
let messageTextClass = 'txt-color-danger';
switch(config.type){
case 'info':
messageTypeClass = 'alert-info';
messageTextClass = 'txt-color-information';
break;
case 'success':
messageTypeClass = 'alert-success';
messageTextClass = 'txt-color-success';
break;
case 'warning':
messageTypeClass = 'alert-warning';
messageTextClass = 'txt-color-warning';
break;
}
let defaultOptions = {
dismissible: true,
messageTypeClass: messageTypeClass,
messageTextClass: messageTextClass
};
defaultOptions = $.extend(defaultOptions, config);
let content = Mustache.render(template, defaultOptions);
containerElement.html(content);
containerElement.children().first().velocity('stop').velocity('fadeIn');
});
};
/**
* wrapper function for onClick() || onDblClick() events in order to distinguish between this two types of events
* @param singleClickCallback
* @param doubleClickCallback
* @param timeout
* @returns {any|JQuery|*}
*/
$.fn.singleDoubleClick = function(singleClickCallback, doubleClickCallback, timeout) {
return this.each(function(){
let clicks = 0, self = this;
// prevent default behaviour (e.g. open <a>-tag link)
$(this).off('click').on('click', function(e){
e.preventDefault();
});
$(this).off('mouseup').on('mouseup', function(e){
clicks++;
if (clicks === 1) {
setTimeout(function(){
if(clicks === 1) {
singleClickCallback.call(self, e);
} else {
doubleClickCallback.call(self, e);
}
clicks = 0;
}, timeout || Init.timer.DBL_CLICK);
}
});
});
};
/**
* highlight jquery elements
* add/remove css class for keyframe animation
* @returns {any|JQuery|*}
*/
$.fn.pulseTableRow = function(status, clear){
let animationClass = '';
switch(status){
case 'added':
animationClass = config.animationPulseSuccessClass;
break;
case 'changed':
animationClass = config.animationPulseWarningClass;
break;
}
let clearTimer = function(element) {
element.removeClass( animationClass );
let currentTimer = element.data('animationTimer');
if( animationTimerCache.hasOwnProperty(currentTimer) ){
clearTimeout( currentTimer );
delete animationTimerCache[currentTimer];
element.removeData('animationTimer');
}
};
return this.each(function(){
let element = $(this);
if( element.hasClass(animationClass) ){
// clear timer -> set new timer
clearTimer(element);
}
if(clear !== true){
element.addClass( animationClass );
let timer = setTimeout(clearTimer, 1500, element);
element.data('animationTimer', timer);
animationTimerCache[timer] = true;
}
});
};
/*
* ===========================================================================================================
* Util functions that are global available for all modules
* ==========================================================================================================
*/
/**
* get current Pathfinder version number
* @returns {*|jQuery}
*/
let getVersion = function(){
return $('body').data('version');
};
/**
* show current program version information in browser console
*/
let showVersionInfo = function(){
console.info('PATHFINDER ' + getVersion());
};
/**
* init utility prototype functions
*/
let initPrototypes = function(){
// Array diff
// [1,2,3,4,5,6].diff( [3,4,5] );
// => [1, 2, 6]
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
};
/**
* flatten XEditable array for select fields
* @param dataArray
* @returns {{}}
*/
let flattenXEditableSelectArray = (dataArray) => {
let flatten = {};
for(let data of dataArray){
if(data.children && data.children.length > 0){
for(let child of data.children){
flatten[child.value] = child.text;
}
}else{
flatten[data.value] = data.text;
}
}
return flatten;
} ;
/**
* set default configuration for "Bootbox" dialogs
*/
let initDefaultBootboxConfig = function(){
bootbox.setDefaults({
onEscape: true // enables close dialogs on ESC key
});
};
/**
* get the current main trigger delay for the main trigger functions
* optional in/decrease the delay
* @param updateKey
* @param value
* @returns {*}
*/
let getCurrentTriggerDelay = function( updateKey, value ){
// make sure the delay timer is valid!
// if this is called for the first time -> set CURRENT_DELAY
if(
Init.timer[updateKey].CURRENT_DELAY === undefined ||
Init.timer[updateKey].CURRENT_DELAY <= 0
){
Init.timer[updateKey].CURRENT_DELAY = Init.timer[updateKey].DELAY;
}
// in/decrease the trigger delay
if(
value === parseInt(value, 10) &&
( Init.timer[updateKey].CURRENT_DELAY ) + value > 0
){
Init.timer[updateKey].CURRENT_DELAY += value;
}
return Init.timer[updateKey].CURRENT_DELAY;
};
/**
* get date obj with current EVE Server Time.
* @returns {Date}
*/
let getServerTime = function(){
// Server is running with GMT/UTC (EVE Time)
let localDate = new Date();
let serverDate= new Date(
localDate.getUTCFullYear(),
localDate.getUTCMonth(),
localDate.getUTCDate(),
localDate.getUTCHours(),
localDate.getUTCMinutes(),
localDate.getUTCSeconds()
);
return serverDate;
};
/**
* convert timestamp to server time
* @param timestamp
* @returns {Date}
*/
let convertTimestampToServerTime = function(timestamp){
let currentTimeZoneOffsetInMinutes = new Date().getTimezoneOffset();
return new Date( (timestamp + (currentTimeZoneOffsetInMinutes * 60)) * 1000);
};
/**
* get date difference as time parts (days, hours, minutes, seconds)
* @param date1
* @param date2
* @returns {{}}
*/
let getTimeDiffParts = function(date1, date2){
let parts = {};
let time1 = date1.getTime();
let time2 = date2.getTime();
let diff = 0;
if(
time1 >= 0 &&
time2 >= 0
){
diff = (date2.getTime() - date1.getTime()) / 1000;
}
diff = Math.abs(Math.floor(diff));
parts.days = Math.floor(diff/(24*60*60));
let leftSec = diff - parts.days * 24*60*60;
parts.hours = Math.floor(leftSec/(60*60));
leftSec = leftSec - parts.hours * 60*60;
parts.min = Math.floor(leftSec/(60));
parts.sec = leftSec - parts.min * 60;
return parts;
};
/**
* start time measurement by a unique string identifier
* @param timerName
*/
let timeStart = function(timerName){
if(typeof performance === 'object'){
stopTimerCache[timerName] = performance.now();
}else{
stopTimerCache[timerName] = new Date().getTime();
}
};
/**
* get time delta between timeStart() and timeStop() by a unique string identifier
* @param timerName
* @returns {number}
*/
let timeStop = function(timerName){
let duration = 0;
if( stopTimerCache.hasOwnProperty(timerName) ){
// check browser support for performance API
let timeNow = 0;
if(typeof performance === 'object'){
timeNow = performance.now();
}else{
timeNow = new Date();
}
// format ms time duration
duration = Number( (timeNow - stopTimerCache[timerName] ).toFixed(2) );
// delete key
delete( stopTimerCache[timerName]);
}
return duration;
};
/**
* trigger main logging event with log information
* @param logKey
* @param options
*/
let log = function(logKey, options){
$(window).trigger('pf:log', [logKey, options]);
};
/**
* trigger a notification (on screen or desktop)
* @param customConfig
* @param desktop
*/
let showNotify = function(customConfig, desktop){
requirejs(['notification'], function(Notification) {
Notification.showNotify(customConfig, desktop);
});
};
/**
* stop browser tab title "blinking"
*/
let stopTabBlink = function(){
requirejs(['notification'], function(Notification) {
Notification.stopTabBlink();
});
};
/**
* get log entry info
* @param logType
* @param option
* @returns {string}
*/
let getLogInfo = function(logType, option){
let logInfo = '';
if(Init.classes.logTypes.hasOwnProperty(logType)){
logInfo = Init.classes.logTypes[logType][option];
}
return logInfo;
};
/**
* get currentUserData from "global" variable
* @returns {*}
*/
let getCurrentUserData = function(){
return Init.currentUserData;
};
/**
* set default jQuery AJAX configuration
*/
let ajaxSetup = function(){
$.ajaxSetup({
beforeSend: function(xhr, settings) {
// Add custom application headers on "same origin" requests only!
// -> Otherwise a "preflight" request is made, which will "probably" fail
if(settings.crossDomain === false){
// add current character data to ANY XHR request (HTTP HEADER)
// -> This helps to identify multiple characters on multiple browser tabs
let userData = getCurrentUserData();
let currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
xhr.setRequestHeader('Pf-Character', currentCharacterId);
}
}
});
};
/**
* get WebSocket readyState description from ID
* https://developer.mozilla.org/de/docs/Web/API/WebSocket
* @param readyState
* @returns {string}
*/
let getWebSocketDescriptionByReadyState = (readyState) => {
let description = '';
switch(readyState){
case 0: description = 'connecting'; break;
case 1: description = 'open'; break;
case 2: description = 'closing'; break;
case 3: description = 'closed'; break;
}
return description;
};
/**
* set sync status for map updates
* -> if SharedWorker AND WebSocket connected -> status = "WebSocket"
* -> else -> status = "ajax" (long polling)
* @param type
* @param options
*/
let setSyncStatus = (type, options) => {
// current syncStatus
let syncStatus = Init.syncStatus;
switch(type){
case 'ws:open':
// WebSocket open
syncStatus.webSocket.status = getWebSocketDescriptionByReadyState(options.readyState);
syncStatus.webSocket.class = 'txt-color-success';
syncStatus.webSocket.timestamp = new Date().getTime() / 1000;
syncStatus.type = 'webSocket';
setSyncStatus('ajax:disable');
$(window).trigger('pf:syncStatus');
break;
case 'ws:get':
// WebSocket data pushed from server
syncStatus.webSocket.timestamp = new Date().getTime() / 1000;
$(window).trigger('pf:syncStatus');
break;
case 'ws:closed':
// WebSocket closed
syncStatus.webSocket.status = getWebSocketDescriptionByReadyState(options.readyState);
syncStatus.webSocket.class = 'txt-color-danger';
syncStatus.webSocket.timestamp = undefined;
setSyncStatus('ajax:enable');
break;
case 'ws:error':
// WebSocket error
syncStatus.webSocket.status = getWebSocketDescriptionByReadyState(options.readyState);
syncStatus.webSocket.class = 'txt-color-danger';
setSyncStatus('ajax:enable');
break;
case 'sw:init':
// SharedWorker initialized
syncStatus.sharedWorker.status = 'online';
syncStatus.sharedWorker.class = 'txt-color-success';
break;
case 'sw:error':
// SharedWorker error
syncStatus.sharedWorker.status = 'offline';
syncStatus.sharedWorker.class = 'txt-color-danger';
setSyncStatus('ajax:enable');
break;
case 'ajax:enable':
// Ajax enabled (WebSocket error/not connected)
syncStatus.ajax.status = 'enabled';
syncStatus.ajax.class = 'txt-color-success';
syncStatus.ajax.timestamp = new Date().getTime() / 1000;
syncStatus.type = 'ajax';
$(window).trigger('pf:syncStatus');
break;
case 'ajax:get':
// Ajax data pulled from client
syncStatus.ajax.timestamp = new Date().getTime() / 1000;
$(window).trigger('pf:syncStatus');
break;
case 'ajax:disable':
// Ajax disabled (WebSocket open/ready)
syncStatus.ajax.status = 'disabled';
syncStatus.ajax.class = 'txt-color-warning';
break;
}
};
/**
* get current sync type for map updates
* -> "ajax" or "webSocket"
* @returns {string}
*/
let getSyncType = () => {
return Init.syncStatus.type;
};
/**
* Returns true if the user hit Esc or navigated away from the
* current page before an AJAX call was done. (The response
* headers will be null or empty, depending on the browser.)
*
* NOTE: this function is only meaningful when called from
* inside an AJAX "error" callback!
* @param jqXHR XMLHttpRequest instance
* @returns {boolean}
*/
let isXHRAborted = function(jqXHR){
return !jqXHR.getAllResponseHeaders();
};
/**
* get all mapTabElements (<a> tags)
* or search for a specific tabElement within the
* mapModuleElement
* @param mapId
* @returns {JQuery|*|{}|T}
*/
$.fn.getMapTabElements = function(mapId){
let mapModuleElement = $(this);
let mapTabElements = mapModuleElement.find('#' + config.mapTabBarId).find('a');
if(mapId){
// search for a specific tab element
mapTabElements = mapTabElements.filter(function(i, el){
return ( $(el).data('map-id') === mapId );
});
}
return mapTabElements;
};
/**
* get mapElement from overlay or any child of that
* @param mapOverlay
* @returns {jQuery}
*/
let getMapElementFromOverlay = (mapOverlay) => {
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
/**
* get the map module object or create a new module
* @returns {*|HTMLElement}
*/
let getMapModule = function(){
let mapModule = $('#' + config.mapModuleId);
if(mapModule.length === 0){
mapModule = $('<div>', {
id: config.mapModuleId
});
}
return mapModule;
};
/**
* get Area ID by security string
* @param security
* @returns {number}
*/
let getAreaIdBySecurity = function(security){
let areaId = 0;
switch(security){
case 'H':
areaId = 10;
break;
case 'L':
areaId = 11;
break;
case '0.0':
areaId = 12;
break;
case 'SH':
areaId = 13;
break;
default:
// w-space
for(let i = 1; i <= 6; i++){
if(security === 'C' + i){
areaId = i;
break;
}
}
break;
}
return areaId;
};
/**
* get system effect data by system security and system class
* if no search parameters given -> get all effect data
* @param security
* @param effect
* @returns {boolean}
*/
let getSystemEffectData = function(security, effect){
let data = SystemEffect;
if(security){
// look for specific data
data = false;
let areaId = getAreaIdBySecurity(security);
if(
areaId > 0 &&
SystemEffect.wh[effect] &&
SystemEffect.wh[effect][areaId]
){
data = SystemEffect.wh[effect][areaId];
}
}
return data;
};
/**
* get status info for a character for a given status
* @param characterData
* @param option
* @returns {string}
*/
let getStatusInfoForCharacter = function(characterData, option){
let statusInfo = '';
// character status can not be checked if there are no reference data
// e.g. during registration process (login page)
if(Init.characterStatus){
// get info for current "main" character
let corporationId = getCurrentUserInfo('corporationId');
let allianceId = getCurrentUserInfo('allianceId');
// get all user characters
let userData = getCurrentUserData();
if(userData){
// check if character is one of his own characters
let userCharactersData = userData.characters;
for(let i = 0; i < userCharactersData.length; i++){
if(userCharactersData[i].id === characterData.id){
statusInfo = Init.characterStatus.own[option];
break;
}
}
}
if(statusInfo === ''){
// compare current user data with given user data
if(
characterData.corporation &&
characterData.corporation.id === corporationId
){
statusInfo = Init.characterStatus.corporation[option];
}else if(
characterData.alliance &&
characterData.alliance.id === allianceId
){
statusInfo = Init.characterStatus.alliance[option];
}
}
}
return statusInfo;
};
/**
* get a HTML table with system effect information
* e.g. for popover
* @param data
* @returns {string}
*/
let getSystemEffectTable = function(data){
let table = '';
if(data.length > 0){
table += '<table>';
for(let i = 0; i < data.length; i++){
table += '<tr>';
table += '<td>';
table += data[i].effect;
table += '</td>';
table += '<td class="text-right">';
table += data[i].value;
table += '</td>';
table += '</tr>';
}
table += '</table>';
}
return table;
};
/**
* get a HTML table with information for multiple systems
* e.g. for popover
* @param data
* @returns {string}
*/
let getSystemsInfoTable = function(data){
let table = '';
if(data.length > 0){
table += '<table>';
for(let i = 0; i < data.length; i++){
let trueSecClass = getTrueSecClassForSystem( data[i].trueSec );
let securityClass = getSecurityClassForSystem( data[i].security );
table += '<tr>';
table += '<td>';
table += data[i].name;
table += '</td>';
table += '<td class="text-right ' + securityClass + '">';
table += data[i].security;
table += '</td>';
table += '<td class="text-right ' + trueSecClass + '">';
table += parseFloat( data[i].trueSec ).toFixed(1);
table += '</td>';
table += '</tr>';
}
table += '</table>';
}
return table;
};
/**
* get a css class for the security level of a system
* @param sec
* @returns {string}
*/
let getSecurityClassForSystem = function(sec){
let secClass = '';
if( Init.classes.systemSecurity.hasOwnProperty(sec) ){
secClass = Init.classes.systemSecurity[sec]['class'];
}
return secClass;
};
/**
* get a css class for the trueSec level of a system
* @param trueSec
* @returns {string}
*/
let getTrueSecClassForSystem = function(trueSec){
let trueSecClass = '';
trueSec = parseFloat(trueSec);
// check for valid decimal number
if(
!isNaN( trueSec ) &&
isFinite( trueSec )
){
if(trueSec < 0){
trueSec = 0;
}
trueSec = trueSec.toFixed(1).toString();
if( Init.classes.trueSec.hasOwnProperty(trueSec) ){
trueSecClass = Init.classes.trueSec[trueSec]['class'];
}
}
return trueSecClass;
};
/**
* get status info
* @param status
* @param option
* @returns {string}
*/
let getStatusInfoForSystem = function(status, option){
let statusInfo = '';
if( Init.systemStatus.hasOwnProperty(status) ){
// search by status string
statusInfo = Init.systemStatus[status][option];
}else{
// saarch by statusID
$.each(Init.systemStatus, function(prop, data){
if(status === data.id){
statusInfo = data[option];
return;
}
});
}
return statusInfo;
};
/**
* get signature group information
* @param option
* @returns {{}}
*/
let getSignatureGroupInfo = function(option){
let groupInfo = {};
for (let prop in Init.signatureGroups) {
if(Init.signatureGroups.hasOwnProperty(prop)){
prop = parseInt(prop);
groupInfo[prop] = Init.signatureGroups[prop][option];
}
}
return groupInfo;
};
/**
* get Signature names out of global
* @param systemTypeId
* @param areaId
* @param sigGroupId
* @returns {{}}
*/
let getAllSignatureNames = function(systemTypeId, areaId, sigGroupId){
let signatureNames = {};
if(
SignatureType[systemTypeId] &&
SignatureType[systemTypeId][areaId] &&
SignatureType[systemTypeId][areaId][sigGroupId]
){
signatureNames = SignatureType[systemTypeId][areaId][sigGroupId];
}
return signatureNames;
};
/**
* get the typeID of a signature name
* @param systemData
* @param sigGroupId
* @param name
* @returns {number}
*/
let getSignatureTypeIdByName = function(systemData, sigGroupId, name){
let signatureTypeId = 0;
let areaId = getAreaIdBySecurity(systemData.security);
if(areaId > 0){
let signatureNames = getAllSignatureNames(systemData.type.id, areaId, sigGroupId );
name = name.toLowerCase();
for(let prop in signatureNames) {
if(
signatureNames.hasOwnProperty(prop) &&
signatureNames[prop].toLowerCase() === name
){
signatureTypeId = parseInt( prop );
break;
}
}
}
return signatureTypeId;
};
/**
* set currentMapUserData as "global" variable (count of active pilots)
* this function should be called continuously after data change
* to keep the data always up2data
* @param mapUserData
*/
let setCurrentMapUserData = function(mapUserData){
Init.currentMapUserData = mapUserData;
return getCurrentMapUserData();
};
/**
* get currentMapUserData from "global" variable for specific map or all maps
* @param mapId
* @returns {boolean}
*/
let getCurrentMapUserData = function(mapId){
let currentMapUserData = false;
if(
mapId === parseInt(mapId, 10) &&
Init.currentMapUserData
){
// search for a specific map
for(let i = 0; i < Init.currentMapUserData.length; i++){
if(Init.currentMapUserData[i].config.id === mapId){
currentMapUserData = Init.currentMapUserData[i];
break;
}
}
}else{
// get data for all maps
currentMapUserData = Init.currentMapUserData;
}
if(currentMapUserData !== false){
// return a fresh (deep) copy of that, in case of further modifications
currentMapUserData = $.extend(true, {}, currentMapUserData);
}
return currentMapUserData;
};
/**
* set currentMapData as "global" variable
* this function should be called continuously after data change
* to keep the data always up2data
* @param mapData
*/
let setCurrentMapData = function(mapData){
Init.currentMapData = mapData;
return getCurrentMapData();
};
/**
* get mapData array index by mapId
* @param mapId
* @returns {boolean|int}
*/
let getCurrentMapDataIndex = function(mapId){
let mapDataIndex = false;
if( mapId === parseInt(mapId, 10) ){
for(let i = 0; i < Init.currentMapData.length; i++){
if(Init.currentMapData[i].config.id === mapId){
mapDataIndex = i;
break;
}
}
}
return mapDataIndex;
};
/**
* update cached mapData for a single map
* @param mapData
*/
let updateCurrentMapData = function(mapData){
let mapDataIndex = getCurrentMapDataIndex( mapData.config.id );
if(mapDataIndex !== false){
Init.currentMapData[mapDataIndex].config = mapData.config;
Init.currentMapData[mapDataIndex].data = mapData.data;
}else{
// new map data
Init.currentMapData.push(mapData);
}
};
/**
* get currentMapData from "global" variable for a specific map or all maps
* @param mapId
* @returns {boolean}
*/
let getCurrentMapData = function(mapId){
let currentMapData = false;
if( mapId === parseInt(mapId, 10) ){
// search for a specific map
for(let i = 0; i < Init.currentMapData.length; i++){
if(Init.currentMapData[i].config.id === mapId){
currentMapData = Init.currentMapData[i];
break;
}
}
}else{
// get data for all maps
currentMapData = Init.currentMapData;
}
return currentMapData;
};
/**
* delete map data by mapId from currentMapData
* @param mapId
*/
let deleteCurrentMapData = (mapId) => {
Init.currentMapData = Init.currentMapData.filter((mapData) => {
return (mapData.config.id !== mapId);
});
};
/**
* set currentUserData as "global" variable
* this function should be called continuously after data change
* to keep the data always up2data
* @param userData
*/
let setCurrentUserData = function(userData){
Init.currentUserData = userData;
// check if function is available
// this is not the case in "login" page
if( $.fn.updateHeaderUserData ){
$.fn.updateHeaderUserData();
}
return getCurrentUserData();
};
/**
* get the current log data for the current user character
* @returns {boolean}
*/
let getCurrentCharacterLog = function(){
let characterLog = false;
let currentUserData = getCurrentUserData();
if(
currentUserData &&
currentUserData.character &&
currentUserData.character.log
){
characterLog = currentUserData.character.log;
}
return characterLog;
};
/**
* get information for the current mail user
* @param option
* @returns {boolean}
*/
let getCurrentUserInfo = function(option){
let currentUserData = getCurrentUserData();
let userInfo = false;
if(currentUserData){
// user data is set -> user data will be set AFTER the main init request!
let characterData = currentUserData.character;
if(characterData){
if(
option === 'allianceId' &&
characterData.alliance
){
userInfo = characterData.alliance.id;
}
if(
option === 'corporationId' &&
characterData.corporation
){
userInfo = characterData.corporation.id;
}
}
}
return userInfo;
};
/**
* get "nearBy" systemData based on a jump radius around a currentSystem
* @param currentSystemData
* @param currentMapData
* @param jumps
* @param foundSystemIds
* @returns {{systemData: *, tree: {}}}
*/
let getNearBySystemData = (currentSystemData, currentMapData, jumps, foundSystemIds = {}) => {
// look for systemData by ID
let getSystemData = (systemId) => {
for(let j = 0; j < currentMapData.data.systems.length; j++){
let systemData = currentMapData.data.systems[j];
if(systemData.id === systemId){
return systemData;
}
}
return false;
};
// skip systems that are already found in recursive calls
foundSystemIds[currentSystemData.id] = {distance: jumps};
let nearBySystems = {
systemData: currentSystemData,
tree: {}
};
jumps--;
if(jumps >= 0){
for(let i = 0; i < currentMapData.data.connections.length; i++){
let connectionData = currentMapData.data.connections[i];
let type = ''; // "source" OR "target"
if(connectionData.source === currentSystemData.id){
type = 'target';
}else if(connectionData.target === currentSystemData.id){
type = 'source';
}
if(
type &&
(
foundSystemIds[connectionData[type]] === undefined ||
foundSystemIds[connectionData[type]].distance < jumps
)
){
let newSystemData = getSystemData(connectionData[type]);
if(newSystemData){
nearBySystems.tree[connectionData[type]] = getNearBySystemData(newSystemData, currentMapData, jumps, foundSystemIds);
}
}
}
}
return nearBySystems;
};
/**
* get current character data from all characters who are "nearby" the current user
* -> see getNearBySystemData()
* @param nearBySystems
* @param userData
* @param jumps
* @param data
* @returns {{}}
*/
let getNearByCharacterData = (nearBySystems, userData, jumps = 0, data = {}) => {
let getCharacterDataBySystemId = (systemId) => {
for(let i = 0; i < userData.length; i++){
if(userData[i].id === systemId){
return userData[i].user;
}
}
return [];
};
let filterFinalCharData = function(tmpFinalCharData){
return this.id !== tmpFinalCharData.id;
};
let characterData = getCharacterDataBySystemId(nearBySystems.systemData.systemId);
if(characterData.length){
// filter (remove) characterData for "already" added chars
characterData = characterData.filter(function(tmpCharacterData, index, allData){
let keepData = true;
for(let tmpJump in data) {
// just scan systems with > jumps than current system
if(tmpJump > jumps){
let filteredFinalData = data[tmpJump].filter(filterFinalCharData, tmpCharacterData);
if(filteredFinalData.length > 0){
data[tmpJump] = filteredFinalData;
}else{
delete data[tmpJump];
}
}else{
for(let k = 0; k < data[tmpJump].length; k++){
if(data[tmpJump][k].id === tmpCharacterData.id){
keepData = false;
break;
}
}
}
}
return keepData;
});
data[jumps] = data[jumps] ? data[jumps] : [];
data[jumps] = [...data[jumps], ...characterData];
}
jumps++;
for(let prop in nearBySystems.tree) {
if( nearBySystems.tree.hasOwnProperty(prop) ){
let tmpSystemData = nearBySystems.tree[prop];
data = getNearByCharacterData(tmpSystemData, userData, jumps, data);
}
}
return data;
};
/**
* set new destination for a system
* @param systemData
* @param type
*/
let setDestination = function(systemData, type){
let description = '';
switch(type){
case 'set_destination':
description = 'Set destination';
break;
case 'add_first_waypoint':
description = 'Set first waypoint';
break;
case 'add_last_waypoint':
description = 'Set new waypoint';
break;
}
$.ajax({
type: 'POST',
url: Init.path.setDestination,
data: {
clearOtherWaypoints: (type === 'set_destination') ? 1 : 0,
first: (type === 'add_last_waypoint') ? 0 : 1,
systemData: [{
systemId: systemData.systemId,
name: systemData.name
}]
},
context: {
description: description
},
dataType: 'json'
}).done(function(responseData){
if(
responseData.systemData &&
responseData.systemData.length > 0
){
for (let j = 0; j < responseData.systemData.length; j++) {
showNotify({title: this.description, text: 'System: ' + responseData.systemData[j].name, type: 'success'});
}
}
if(
responseData.error &&
responseData.error.length > 0
){
for(let i = 0; i < responseData.error.length; i++){
showNotify({title: this.description + ' error', text: 'System: ' + responseData.error[i].message, type: 'error'});
}
}
}).fail(function( jqXHR, status, error) {
let reason = status + ' ' + error;
showNotify({title: jqXHR.status + ': ' + this.description, text: reason, type: 'warning'});
});
};
/**
* set currentSystemData as "global" variable
* @param systemData
*/
let setCurrentSystemData = function(systemData){
Init.currentSystemData = systemData;
};
/**
* get currentSystemData from "global" variables
* @returns {*}
*/
let getCurrentSystemData = function(){
return Init.currentSystemData;
};
/**
* get current location data
* -> system data where current user is located
* @returns {{id: *, name: *}}
*/
let getCurrentLocationData = function(){
let currentLocationLink = $('#' + config.headCurrentLocationId).find('a');
return {
id: currentLocationLink.data('systemId'),
name: currentLocationLink.data('systemName')
};
};
/**
* get all "open" dialog elements
* @returns {*|jQuery}
*/
let getOpenDialogs = function(){
return $('.' + config.dialogClass).filter(':visible');
};
/**
* send Ajax request that remote opens an ingame Window
* @param targetId
*/
let openIngameWindow = (targetId) => {
targetId = parseInt(targetId);
if(targetId > 0){
$.ajax({
type: 'POST',
url: Init.path.openIngameWindow,
data: {
targetId: targetId
},
dataType: 'json'
}).done(function(data){
if(data.error.length > 0){
showNotify({title: 'Open window in client', text: 'Remote window open failed', type: 'error'});
}else{
showNotify({title: 'Open window in client', text: 'Check your EVE client', type: 'success'});
}
}).fail(function( jqXHR, status, error) {
let reason = status + ' ' + error;
showNotify({title: jqXHR.status + ': openWindow', text: reason, type: 'error'});
});
}
};
/**
* formats a price string into an ISK Price
* @param price
* @returns {string}
*/
let formatPrice = function(price){
price = Number( price ).toFixed(2);
let parts = price.toString().split('.');
price = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (parts[1] ? '.' + parts[1] : '');
return price + ' ISK';
};
/**
* get localForage instance (singleton) for offline client site storage
* @returns {localforage}
*/
let getLocalStorage = function(){
if(localStorage === undefined){
localStorage = localforage.createInstance({
driver: [localforage.INDEXEDDB, localforage.WEBSQL, localforage.LOCALSTORAGE],
name: 'Pathfinder local storage'
});
}
return localStorage;
};
/**
* Create Date as UTC
* @param date
* @returns {Date}
*/
let createDateAsUTC = function(date) {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
};
/**
* Convert Date to UTC (!important function!)
* @param date
* @returns {Date}
*/
let convertDateToUTC = function(date) {
return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
};
/**
* Convert Date to Time String
* @param date
* @returns {string}
*/
let convertDateToString = function(date){
let dateString = ('0'+ (date.getMonth() + 1 )).slice(-2) + '/' + ('0'+date.getDate()).slice(-2) + '/' + date.getFullYear();
let timeString = ('0' + date.getHours()).slice(-2) + ':' + ('0'+date.getMinutes()).slice(-2);
return dateString + ' ' + timeString;
};
/**
* get document path
* -> www.pathfinder.com/pathfinder/ -> /pathfinder
* @returns {string|string}
*/
let getDocumentPath = function(){
let pathname = window.location.pathname;
// replace file endings
let r = /[^\/]*$/;
let path = pathname.replace(r, '');
return path || '/';
};
/**
* redirect
* @param url
* @param params
*/
let redirect = function(url, params){
let currentUrl = document.URL;
if(url !== currentUrl){
if(
params &&
params.length > 0
){
url += '?' + params.join('&');
}
window.location = url;
}
};
/**
* send logout request
* @param params
*/
let logout = function(params){
let data = {};
if(
params &&
params.ajaxData
){
data = params.ajaxData;
}
$.ajax({
type: 'POST',
url: Init.path.logout,
data: data,
dataType: 'json'
}).done(function(data){
if(data.reroute){
redirect(data.reroute, ['logout']);
}
}).fail(function( jqXHR, status, error) {
let reason = status + ' ' + error;
showNotify({title: jqXHR.status + ': logout', text: reason, type: 'error'});
});
};
return {
config: config,
getVersion: getVersion,
showVersionInfo: showVersionInfo,
initPrototypes: initPrototypes,
initDefaultBootboxConfig: initDefaultBootboxConfig,
getCurrentTriggerDelay: getCurrentTriggerDelay,
getServerTime: getServerTime,
convertTimestampToServerTime: convertTimestampToServerTime,
getTimeDiffParts: getTimeDiffParts,
timeStart: timeStart,
timeStop: timeStop,
log: log,
showNotify: showNotify,
stopTabBlink: stopTabBlink,
getLogInfo: getLogInfo,
ajaxSetup: ajaxSetup,
setSyncStatus: setSyncStatus,
getSyncType: getSyncType,
isXHRAborted: isXHRAborted,
getMapElementFromOverlay: getMapElementFromOverlay,
getMapModule: getMapModule,
getSystemEffectData: getSystemEffectData,
getSystemEffectTable: getSystemEffectTable,
getSystemsInfoTable: getSystemsInfoTable,
getStatusInfoForCharacter: getStatusInfoForCharacter,
getSecurityClassForSystem: getSecurityClassForSystem,
getTrueSecClassForSystem: getTrueSecClassForSystem,
getStatusInfoForSystem: getStatusInfoForSystem,
getSignatureGroupInfo: getSignatureGroupInfo,
getAllSignatureNames: getAllSignatureNames,
getSignatureTypeIdByName: getSignatureTypeIdByName,
getAreaIdBySecurity: getAreaIdBySecurity,
setCurrentMapUserData: setCurrentMapUserData,
getCurrentMapUserData: getCurrentMapUserData,
setCurrentMapData: setCurrentMapData,
getCurrentMapData: getCurrentMapData,
getCurrentMapDataIndex: getCurrentMapDataIndex,
updateCurrentMapData: updateCurrentMapData,
deleteCurrentMapData: deleteCurrentMapData,
setCurrentUserData: setCurrentUserData,
getCurrentUserData: getCurrentUserData,
setCurrentSystemData: setCurrentSystemData,
getCurrentSystemData: getCurrentSystemData,
getCurrentLocationData: getCurrentLocationData,
getCurrentUserInfo: getCurrentUserInfo,
getCurrentCharacterLog: getCurrentCharacterLog,
flattenXEditableSelectArray: flattenXEditableSelectArray,
getNearBySystemData: getNearBySystemData,
getNearByCharacterData: getNearByCharacterData,
setDestination: setDestination,
convertDateToString: convertDateToString,
getOpenDialogs: getOpenDialogs,
openIngameWindow: openIngameWindow,
formatPrice: formatPrice,
getLocalStorage: getLocalStorage,
getDocumentPath: getDocumentPath,
redirect: redirect,
logout: logout
};
});