2266 lines
79 KiB
JavaScript
2266 lines
79 KiB
JavaScript
/**
|
||
* Map util functions
|
||
*/
|
||
|
||
define([
|
||
'jquery',
|
||
'app/init',
|
||
'app/util',
|
||
'app/map/layout',
|
||
'app/map/scrollbar',
|
||
'app/map/overlay/util'
|
||
], ($, Init, Util, Layout, Scrollbar, MapOverlayUtil) => {
|
||
'use strict';
|
||
|
||
let config = {
|
||
mapSnapToGridDimension: 20, // px for grid snapping (grid YxY)
|
||
defaultLocalJumpRadius: 3, // default search radius (in jumps) for "nearby" pilots
|
||
zoomMax: 1.5,
|
||
zoomMin: 0.5,
|
||
|
||
mapGridClass: 'pf-grid-small', // class for map grid snapping
|
||
systemRegionClass: 'pf-map-region', // class for systems regions on map
|
||
systemCompactClass: 'pf-map-compact', // class for compact systems on map
|
||
|
||
systemIdPrefix: 'pf-system-', // id prefix for a system
|
||
systemClass: 'pf-system', // class for all systems
|
||
systemActiveClass: 'pf-system-active', // class for an active system on a map
|
||
systemSelectedClass: 'pf-system-selected', // class for selected systems on on map
|
||
systemLockedClass: 'pf-system-locked', // class for locked systems on a map
|
||
systemHiddenClass: 'pf-system-hidden', // class for hidden (filtered) systems
|
||
|
||
// dataTable
|
||
tableCellEllipsisClass: 'pf-table-cell-ellipsis',
|
||
tableCellEllipsis80Class: 'pf-table-cell-80',
|
||
tableCellEllipsis90Class: 'pf-table-cell-90',
|
||
tableCellEllipsis100Class: 'pf-table-cell-100'
|
||
};
|
||
|
||
// active jsPlumb instances currently running =====================================================================
|
||
let activeInstances = {};
|
||
|
||
/**
|
||
* set mapInstance
|
||
* @param mapId
|
||
* @param map
|
||
*/
|
||
let setMapInstance = (mapId, map) => {
|
||
activeInstances[mapId] = map;
|
||
};
|
||
|
||
/**
|
||
* get mapInstance
|
||
* @param mapId
|
||
* @returns {*}
|
||
*/
|
||
let getMapInstance = mapId => activeInstances[mapId];
|
||
|
||
/**
|
||
* check for mapInstance is set
|
||
* @param mapId
|
||
* @returns {boolean}
|
||
*/
|
||
let existsMapInstance = mapId => typeof activeInstances[mapId] === 'object';
|
||
|
||
/**
|
||
* removes a map instance
|
||
* @param mapId
|
||
*/
|
||
let clearMapInstance = mapId => {
|
||
if(existsMapInstance(mapId)){
|
||
delete activeInstances[mapId];
|
||
}
|
||
};
|
||
|
||
// ================================================================================================================
|
||
|
||
/**
|
||
* get all available map Types
|
||
* optional they can be filtered by current access level of current character
|
||
* @param {bool} filterByCharacter
|
||
* @param {string} filterRight
|
||
* @returns {Array}
|
||
*/
|
||
let getMapTypes = (filterByCharacter, filterRight) => {
|
||
let mapTypes = Object.assign({}, Init.mapTypes);
|
||
|
||
if(filterByCharacter === true){
|
||
let authorizedMapTypes = [];
|
||
let checkMapTypes = [
|
||
{type: 'private', hasRight: false, selector: 'id'},
|
||
{type: 'corporation', hasRight: true, selector: 'corporation.id'},
|
||
{type: 'alliance', hasRight: false, selector: 'alliance.id'}
|
||
];
|
||
|
||
checkMapTypes.forEach(data => {
|
||
// check if current character is e.g. in alliance
|
||
if(Util.getCurrentCharacterData(data.selector)){
|
||
// check if User could add new map with a mapType -> check map limit
|
||
let currentObjectMapData = Util.filterCurrentMapData('config.type.id', Util.getObjVal(mapTypes, data.selector));
|
||
let maxCountObject = Util.getObjVal(mapTypes, `${data.type}.defaultConfig.max_count`);
|
||
if(currentObjectMapData.length < maxCountObject){
|
||
// check if character has the "right" for creating a map with this type
|
||
if((data.hasRight && filterRight) ? Util.hasRight(filterRight, data.type) : true){
|
||
authorizedMapTypes.push(data.type);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
mapTypes = Util.filterObjByKeys(mapTypes, authorizedMapTypes);
|
||
}
|
||
|
||
// add "name" to mapType data
|
||
Object.entries(mapTypes).forEach(([mapType, data]) => {
|
||
data.name = mapType;
|
||
});
|
||
|
||
// obj to array
|
||
return Object.keys(mapTypes).map(mapType => mapTypes[mapType]);
|
||
};
|
||
|
||
/**
|
||
* get all available scopes for a map
|
||
* @returns {Array}
|
||
*/
|
||
let getMapScopes = () => {
|
||
let scopes = [];
|
||
$.each(Init.mapScopes, function(prop, data){
|
||
let tempData = data;
|
||
tempData.name = prop;
|
||
scopes.push(tempData);
|
||
});
|
||
|
||
return scopes;
|
||
};
|
||
|
||
/**
|
||
* get some scope info for a given info string
|
||
* @param {string} info
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getScopeInfoForMap = (info, option) => {
|
||
let scopeInfo = '';
|
||
if(Init.mapScopes.hasOwnProperty(info)){
|
||
scopeInfo = Init.mapScopes[info][option];
|
||
}
|
||
return scopeInfo;
|
||
};
|
||
|
||
/**
|
||
* get all available map icons
|
||
* @returns {Object[]}
|
||
*/
|
||
let getMapIcons = () => {
|
||
return Init.mapIcons;
|
||
};
|
||
|
||
/**
|
||
* get map info
|
||
* @param {string} mapType
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getInfoForMap = (mapType, option) => {
|
||
let mapInfo = '';
|
||
if(Init.mapTypes.hasOwnProperty(mapType)){
|
||
mapInfo = Init.mapTypes[mapType][option];
|
||
}
|
||
return mapInfo;
|
||
};
|
||
|
||
/**
|
||
* get some system info for a given info string (e.g. rally class)
|
||
* @param {string} info
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getInfoForSystem = (info, option) => {
|
||
let systemInfo = '';
|
||
if(Init.classes.systemInfo.hasOwnProperty(info)){
|
||
systemInfo = Init.classes.systemInfo[info][option];
|
||
}
|
||
return systemInfo;
|
||
};
|
||
|
||
/**
|
||
* get system data from mapData
|
||
* @see getSystemData
|
||
* @param mapData
|
||
* @param value
|
||
* @param key
|
||
* @returns {{}|boolean}
|
||
*/
|
||
let getSystemDataFromMapData = (mapData, value, key = 'id') => {
|
||
return (Util.getObjVal(mapData, `data.systems`) || [])
|
||
.find(systemData => systemData[key] === value) || false;
|
||
};
|
||
|
||
/**
|
||
* get system data by mapId + system data selector
|
||
* -> e.g. value = 2 and key = 'id'
|
||
* -> e.g. value = 30002187 and key = 'systemId' => looks for 'Amarr' CCP systemId
|
||
* @param mapId
|
||
* @param value
|
||
* @param key
|
||
* @returns {{}|boolean}
|
||
*/
|
||
let getSystemData = (mapId, value, key = 'id') => {
|
||
return getSystemDataFromMapData(Util.getCurrentMapData(mapId), value, key);
|
||
};
|
||
|
||
/**
|
||
* get connection data from mapData
|
||
* @see getConnectionData
|
||
* @param mapData
|
||
* @param value
|
||
* @param key
|
||
* @returns {{}|boolean}
|
||
*/
|
||
let getConnectionDataFromMapData = (mapData, value, key = 'id') => {
|
||
return (Util.getObjVal(mapData, `data.connections`) || [])
|
||
.find(connectionData => connectionData[key] === value) || false;
|
||
};
|
||
|
||
/**
|
||
* get connection data by mapId + connection data selector
|
||
* @param mapId
|
||
* @param value
|
||
* @param key
|
||
* @returns {{}|boolean}
|
||
*/
|
||
let getConnectionData = (mapId, value, key = 'id') => {
|
||
return getConnectionDataFromMapData(Util.getCurrentMapData(mapId), value, key);
|
||
};
|
||
|
||
/**
|
||
* get system type information
|
||
* @param {number} systemTypeId
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getSystemTypeInfo = (systemTypeId, option) => {
|
||
return (Object.values(Init.systemType).find(data => data.id === systemTypeId) || {})[option] || '';
|
||
};
|
||
|
||
/**
|
||
* get some info for a given effect string
|
||
* @param effect
|
||
* @param option
|
||
* @returns {string}
|
||
*/
|
||
let getEffectInfoForSystem = (effect, option) => {
|
||
return Util.getObjVal(Init.classes.systemEffects, `${effect}.${option}`) || '';
|
||
};
|
||
|
||
/**
|
||
* flag map component (map, system, connection) as "changed"
|
||
* @param component
|
||
*/
|
||
let markAsChanged = component => {
|
||
if(component instanceof $ && component.hasClass(config.systemClass)){
|
||
component.data('changed', true);
|
||
}else if(component instanceof jsPlumb.Connection){
|
||
component.setParameter('changed', true);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* check if map component (system, connection) is flagged as "changed"
|
||
* @param component
|
||
* @returns {boolean}
|
||
*/
|
||
let hasChanged = component => {
|
||
let changed = false;
|
||
if(component instanceof $ && component.hasClass(config.systemClass)){
|
||
changed = component.data('changed') || false;
|
||
}else if(component instanceof jsPlumb.Connection){
|
||
changed = component.getParameter('changed') || false;
|
||
}
|
||
return changed;
|
||
};
|
||
|
||
/**
|
||
* get system elements on a map
|
||
* @returns {*|jQuery}
|
||
*/
|
||
$.fn.getSystems = function(){
|
||
return this.find('.' + config.systemClass);
|
||
};
|
||
|
||
/**
|
||
* get all selected (NOT active) systems on a map
|
||
* @returns {*}
|
||
*/
|
||
$.fn.getSelectedSystems = function(){
|
||
let mapElement = $(this);
|
||
return mapElement.find('.' + config.systemSelectedClass);
|
||
};
|
||
|
||
/**
|
||
* filter jsPlumb connection or endpoint types
|
||
* -> remove default type(s)
|
||
* @param types
|
||
* @returns {*}
|
||
*/
|
||
let filterDefaultTypes = types => {
|
||
let defaultTypes = ['', 'default', 'info_signature', 'state_active', 'state_process'];
|
||
return types.diff(defaultTypes);
|
||
};
|
||
|
||
/**
|
||
* returns "target/source" label from endpoint
|
||
* @param connection
|
||
* @param endpoint
|
||
* @returns {string}
|
||
*/
|
||
let getEndpointLabel = (connection, endpoint) => {
|
||
return endpoint.element === connection.source ? 'source' : endpoint.element === connection.target ? 'target' : false;
|
||
};
|
||
|
||
/**
|
||
* get data from endpoint
|
||
* @param connection
|
||
* @param endpoint
|
||
* @returns {{types: *, label: string}}
|
||
*/
|
||
let getDataByEndpoint = (connection, endpoint) => {
|
||
return {
|
||
label: getEndpointLabel(connection, endpoint),
|
||
types: filterDefaultTypes(endpoint.getType())
|
||
};
|
||
};
|
||
|
||
/**
|
||
* filter connections by type
|
||
* @param map
|
||
* @param type
|
||
* @param exclude
|
||
* @returns {Array}
|
||
*/
|
||
let getConnectionsByType = (map, type, exclude = false) => {
|
||
let connections = [];
|
||
for(let data of map.select().hasType(type)){
|
||
if(data[0] !== exclude){
|
||
connections.push(data[1]);
|
||
}
|
||
}
|
||
return connections;
|
||
};
|
||
|
||
/**
|
||
* get endpoints data from connection
|
||
* @param connection
|
||
* @returns {{source: {}, target: {}}}
|
||
*/
|
||
let getEndpointsDataByConnection = connection => {
|
||
let endpointsData = {source: {}, target: {}};
|
||
for(let endpoint of connection.endpoints){
|
||
let endpointData = getDataByEndpoint(connection, endpoint);
|
||
if(endpointData.label === 'source'){
|
||
endpointsData.source = endpointData;
|
||
}else if(endpointData.label === 'target'){
|
||
endpointsData.target = endpointData;
|
||
}
|
||
}
|
||
return endpointsData;
|
||
};
|
||
|
||
/**
|
||
* get connection data from connection
|
||
* @param connection
|
||
* @param minimal
|
||
* @returns {{id: (*|number), updated: (*|number)}}
|
||
*/
|
||
let getDataByConnection = (connection, minimal = false) => {
|
||
let source = $(connection.source);
|
||
let target = $(connection.target);
|
||
|
||
let connectionData = {
|
||
id: connection.getParameter('connectionId') || 0,
|
||
updated: connection.getParameter('updated') || 0,
|
||
source: parseInt(source.data('id')),
|
||
target: parseInt(target.data('id'))
|
||
};
|
||
|
||
if(minimal){
|
||
connectionData = Object.assign(connectionData, {
|
||
connection: connection
|
||
});
|
||
}else{
|
||
connectionData = Object.assign(connectionData, {
|
||
sourceName: source.data('name'),
|
||
sourceAlias: source.getSystemInfo(['alias']) || source.data('name'),
|
||
targetName: target.data('name'),
|
||
targetAlias: target.getSystemInfo(['alias']) || target.data('name'),
|
||
scope: connection.scope,
|
||
type: filterDefaultTypes(connection.getType()),
|
||
endpoints: getEndpointsDataByConnection(connection)
|
||
});
|
||
}
|
||
|
||
return connectionData;
|
||
};
|
||
|
||
/**
|
||
* @see getDataByConnection
|
||
* @param connections
|
||
* @returns {Array}
|
||
*/
|
||
let getDataByConnections = connections => {
|
||
let data = [];
|
||
for(let connection of connections){
|
||
data.push(getDataByConnection(connection));
|
||
}
|
||
return data;
|
||
};
|
||
|
||
/**
|
||
* delete a connection and all related data
|
||
* @param connections
|
||
* @param callback
|
||
*/
|
||
let deleteConnections = (connections, callback) => {
|
||
if(connections.length > 0){
|
||
|
||
// remove connections from map
|
||
let removeConnections = connections => {
|
||
for(let connection of connections){
|
||
connection._jsPlumb.instance.deleteConnection(connection, {fireEvent: false});
|
||
}
|
||
};
|
||
|
||
// prepare delete request
|
||
let map = connections[0]._jsPlumb.instance;
|
||
let mapContainer = $(map.getContainer());
|
||
|
||
// connectionIds for delete request
|
||
let connectionIds = [];
|
||
for(let connection of connections){
|
||
connection.addType('state_process');
|
||
|
||
let connectionId = connection.getParameter('connectionId');
|
||
// drag&drop a new connection does not have an id yet, if connection is not established correct
|
||
if(connectionId !== undefined){
|
||
connectionIds.push(connectionId);
|
||
}
|
||
}
|
||
|
||
if(connectionIds.length > 0){
|
||
Util.request('DELETE', 'Connection', connectionIds, {
|
||
mapId: mapContainer.data('id')
|
||
}, {
|
||
connections: connections
|
||
}).then(
|
||
payload => {
|
||
for(let connection of payload.context.connections){
|
||
// connection might be removed rom global map update before this requests ends
|
||
if(connection._jsPlumb){
|
||
connection.removeType('state_process');
|
||
}
|
||
}
|
||
|
||
// check if all connections were deleted that should get deleted
|
||
let deletedConnections = payload.context.connections.filter(
|
||
function(connection){
|
||
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
|
||
// connection is already deleted!
|
||
return (
|
||
connection._jsPlumb &&
|
||
this.indexOf( connection.getParameter('connectionId') ) !== -1
|
||
);
|
||
}, payload.data
|
||
);
|
||
|
||
// remove connections from map
|
||
removeConnections(deletedConnections);
|
||
|
||
if(callback){
|
||
callback();
|
||
}
|
||
},
|
||
Util.handleAjaxErrorResponse
|
||
);
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* get connection related data from a connection
|
||
* -> data requires a signature bind to that connection
|
||
* @param connection
|
||
* @param connectionData
|
||
* @returns {{source: {names: Array, labels: Array}, target: {names: Array, labels: Array}}}
|
||
*/
|
||
let getConnectionDataFromSignatures = (connection, connectionData) => {
|
||
let signatureTypeData = {
|
||
source: {
|
||
ids: [],
|
||
names: [],
|
||
labels: []
|
||
},
|
||
target: {
|
||
ids: [],
|
||
names: [],
|
||
labels: []
|
||
},
|
||
hash: false // unique hash key build from all relevant signature for connection
|
||
};
|
||
|
||
if(
|
||
connection &&
|
||
connectionData &&
|
||
connectionData.signatures // signature data is required...
|
||
){
|
||
let SystemSignatureModule = require('module/system_signature');
|
||
|
||
let sourceEndpoint = connection.endpoints[0];
|
||
let targetEndpoint = connection.endpoints[1];
|
||
let sourceSystem = $(sourceEndpoint.element);
|
||
let targetSystem = $(targetEndpoint.element);
|
||
let sourceId = sourceSystem.data('id');
|
||
let targetId = targetSystem.data('id');
|
||
|
||
// in case connection is currently "dragged" between systems, sourceId and/or targetId is undefined
|
||
if(!sourceId || !targetId){
|
||
return signatureTypeData;
|
||
}
|
||
|
||
let hash = [];
|
||
// ... collect overlay/label data from signatures
|
||
for(let signatureData of connectionData.signatures){
|
||
hash.push(Util.getObjVal(signatureData, 'updated.updated'));
|
||
|
||
// whether "source" or "target" system is relevant for current connection and current signature...
|
||
let tmpSystem = null;
|
||
let tmpSystemType = null;
|
||
|
||
if(signatureData.system.id === sourceId){
|
||
// relates to "source" endpoint
|
||
tmpSystemType = 'source';
|
||
tmpSystem = sourceSystem;
|
||
}else if(signatureData.system.id === targetId){
|
||
// relates to "target" endpoint
|
||
tmpSystemType = 'target';
|
||
tmpSystem = targetSystem;
|
||
}
|
||
|
||
signatureTypeData[tmpSystemType].ids.push(signatureData.id);
|
||
signatureTypeData[tmpSystemType].names.push(signatureData.name.toUpperCase());
|
||
|
||
// ... typeId is required to get a valid labels
|
||
// ... get endpoint label for source || target system
|
||
if(signatureData.typeId > 0 && tmpSystem && tmpSystem){
|
||
// ... get all available signature type (wormholes) names
|
||
let availableSigTypeNames = SystemSignatureModule.getSignatureTypeOptionsBySystem(tmpSystem, 5);
|
||
let flattenSigTypeNames = Util.flattenXEditableSelectArray(availableSigTypeNames);
|
||
|
||
if(flattenSigTypeNames.hasOwnProperty(signatureData.typeId)){
|
||
let label = flattenSigTypeNames[signatureData.typeId];
|
||
// shorten label, just take the ingame name
|
||
label = label.substr(0, label.indexOf(' '));
|
||
signatureTypeData[tmpSystemType].labels.push(label);
|
||
}
|
||
}
|
||
}
|
||
// ... build unique hash
|
||
signatureTypeData.hash = hash.join().hashCode();
|
||
}
|
||
|
||
return signatureTypeData;
|
||
};
|
||
|
||
/**
|
||
* get Location [x,y] for Endpoint Overlays (e.g. wh type from Signature mapping)
|
||
* -> Coordinates are relative to the Endpoint (not the system!)
|
||
* -> jsPlumb specific format
|
||
* @param endpoint
|
||
* @param labels
|
||
* @returns {number[]}
|
||
*/
|
||
let getEndpointOverlaySignatureLocation = (endpoint, labels) => {
|
||
let defaultLocation = [0.5, 0.5];
|
||
|
||
if(endpoint.anchor.getCurrentFace){
|
||
// ContinuousAnchor
|
||
let count = labels.length;
|
||
let xLeft = count ? count === 1 ? -1.00 : 3 : -0.5;
|
||
let xRight = count ? count === 1 ? +2.20 : 3 : +1.5;
|
||
|
||
switch(endpoint.anchor.getCurrentFace()){
|
||
case 'top': return [0.5, -0.75];
|
||
case 'left': return [xLeft, 0.25];
|
||
case 'right': return [xRight, 0.25];
|
||
case 'bottom': return [0.5 , 1.75];
|
||
default: return defaultLocation;
|
||
}
|
||
}else{
|
||
// e.g. floating endpoint (dragging)
|
||
// -> ContinuousAnchor
|
||
return defaultLocation;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* get overlay HTML for connection endpoints by Label array
|
||
* @param labels
|
||
* @returns {string}
|
||
*/
|
||
let formatEndpointOverlaySignatureLabel = labels => {
|
||
// default K162 in label array, or multiple labels
|
||
let colorClass = 'txt-color-grayLighter';
|
||
let label = labels.join(', ');
|
||
|
||
if(labels.length === 0){
|
||
// endpoint not connected with a signature
|
||
label = '<i class="fas fa-question-circle"></i>';
|
||
colorClass = 'txt-color-red';
|
||
}else if(
|
||
labels.length === 1 &&
|
||
!labels.includes('K162')
|
||
){
|
||
colorClass = Init.wormholes[labels[0]].class;
|
||
}
|
||
|
||
return '<span class="txt-color ' + colorClass + '">' + label + '</span>';
|
||
};
|
||
|
||
/**
|
||
* get TabContentElement by any element on a map e.g. system
|
||
* @param element
|
||
* @returns {*}
|
||
*/
|
||
let getTabContentElementByMapElement = element => $(element).closest('.' + Util.config.mapTabContentClass);
|
||
|
||
/**
|
||
* checks if there is an "active" connection on a map
|
||
* @param map
|
||
* @returns {boolean}
|
||
*/
|
||
let hasActiveConnection = map => {
|
||
let activeConnections = getConnectionsByType(map, 'state_active');
|
||
return activeConnections.length > 0;
|
||
};
|
||
|
||
/**
|
||
* filter map by scopes
|
||
* -> this effects visible systems and connections on UI
|
||
* @param map
|
||
* @param scopes
|
||
*/
|
||
let filterMapByScopes = (map, scopes) => {
|
||
if(map){
|
||
map.setSuspendDrawing(true);
|
||
|
||
let mapElement = $(map.getContainer());
|
||
let allSystems = mapElement.getSystems();
|
||
let allConnections = map.getAllConnections();
|
||
|
||
if(scopes && scopes.length){
|
||
// filter connections -------------------------------------------------------------------------------------
|
||
let visibleSystems = [];
|
||
let visibleConnections = searchConnectionsByScopeAndType(map, scopes);
|
||
|
||
for(let connection of allConnections){
|
||
if(visibleConnections.indexOf(connection) >= 0){
|
||
setConnectionVisible(connection, true);
|
||
// source/target system should always be visible -> even if filter scope not matches system type
|
||
if(visibleSystems.indexOf(connection.endpoints[0].element) < 0){
|
||
visibleSystems.push(connection.endpoints[0].element);
|
||
}
|
||
if(visibleSystems.indexOf(connection.endpoints[1].element) < 0){
|
||
visibleSystems.push(connection.endpoints[1].element);
|
||
}
|
||
}else{
|
||
setConnectionVisible(connection, false);
|
||
}
|
||
}
|
||
|
||
// filter systems -----------------------------------------------------------------------------------------
|
||
let visibleTypeIds = [];
|
||
if(scopes.indexOf('wh') >= 0){
|
||
visibleTypeIds.push(1);
|
||
}
|
||
if(scopes.indexOf('abyssal') >= 0){
|
||
visibleTypeIds.push(4);
|
||
}
|
||
|
||
for(let system of allSystems){
|
||
if(
|
||
visibleTypeIds.indexOf($(system).data('typeId')) >= 0 ||
|
||
visibleSystems.indexOf(system) >= 0
|
||
){
|
||
setSystemVisible(system, map, true);
|
||
}else{
|
||
setSystemVisible(system, map, false);
|
||
}
|
||
}
|
||
|
||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'show');
|
||
}else{
|
||
// clear filter
|
||
for(let system of allSystems){
|
||
setSystemVisible(system, map, true);
|
||
}
|
||
for(let connection of allConnections){
|
||
setConnectionVisible(connection, true);
|
||
}
|
||
|
||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'hide');
|
||
}
|
||
|
||
map.setSuspendDrawing(false, true);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* in/de-crease zoom level
|
||
* @param map
|
||
* @param zoomAction
|
||
* @returns {boolean}
|
||
*/
|
||
let changeZoom = (map, zoomAction) => {
|
||
let zoomChange = false;
|
||
let zoom = map.getZoom();
|
||
let zoomStep = 0.1;
|
||
if('up' === zoomAction){
|
||
zoom += zoomStep;
|
||
}else{
|
||
zoom -= zoomStep;
|
||
}
|
||
zoom = Math.round(zoom * 10) / 10;
|
||
if(zoom >= config.zoomMin && zoom <= config.zoomMax){
|
||
zoomChange = setZoom(map, zoom);
|
||
}
|
||
return zoomChange;
|
||
};
|
||
|
||
/**
|
||
* set zoom level for a map
|
||
* @param map
|
||
* @param zoom
|
||
* @returns {boolean}
|
||
*/
|
||
let setZoom = (map, zoom = 1) => {
|
||
let zoomChange = false;
|
||
if(zoom !== map.getZoom()){
|
||
// zoom jsPlumb map http://jsplumb.github.io/jsplumb/zooming.html
|
||
let transformOrigin = [0, 0];
|
||
let el = map.getContainer();
|
||
let p = ['webkit', 'moz', 'ms', 'o'];
|
||
let s = 'scale(' + zoom + ')';
|
||
let oString = (transformOrigin[0] * 100) + '% ' + (transformOrigin[1] * 100) + '%';
|
||
|
||
for(let i = 0; i < p.length; i++){
|
||
el.style[p[i] + 'Transform'] = s;
|
||
el.style[p[i] + 'TransformOrigin'] = oString;
|
||
}
|
||
el.style.transform = s;
|
||
el.style.transformOrigin = oString;
|
||
|
||
zoomChange = map.setZoom(zoom);
|
||
|
||
// adjust mCustomScrollbar --------------------------------------------------------------------------------
|
||
let scaledWidth = el.getBoundingClientRect().width;
|
||
let scaledHeight = el.getBoundingClientRect().height;
|
||
let mapContainer = $(el);
|
||
let mapWidth = mapContainer.outerWidth(); // this is fix (should never change)
|
||
let mapHeight = mapContainer.outerHeight(); // this is fix (should never change)
|
||
let wrapperWidth = mapContainer.parents('.mCSB_container_wrapper').outerWidth(); // changes on browser resize (map window)
|
||
let wrapperHeight = mapContainer.parents('.mCSB_container_wrapper').outerHeight(); // changes on drag resize (map window)
|
||
let scrollableWidth = (zoom === 1 || mapWidth !== scaledWidth && scaledWidth > wrapperWidth);
|
||
let scrollableHeight = (zoom === 1 || mapHeight !== scaledHeight && scaledHeight > wrapperHeight);
|
||
|
||
mapContainer.parents('.mCSB_container').css({
|
||
'width': scrollableWidth ? scaledWidth + 'px' : (wrapperWidth - 50) + 'px',
|
||
'height': scrollableHeight ? scaledHeight + 'px' : (wrapperHeight) + 'px',
|
||
});
|
||
|
||
let areaMap = mapContainer.closest('.mCustomScrollbar');
|
||
if(scrollableWidth && scrollableHeight){
|
||
areaMap.mCustomScrollbar('update');
|
||
}else{
|
||
areaMap.mCustomScrollbar('scrollTo', '#' + mapContainer.attr('id'), {
|
||
scrollInertia: 0,
|
||
scrollEasing: 'linear',
|
||
timeout: 0,
|
||
moveDragger: false
|
||
});
|
||
}
|
||
}
|
||
|
||
return zoomChange;
|
||
};
|
||
|
||
/**
|
||
* toggles editable input form for system rename (set alias)
|
||
* @param system
|
||
*/
|
||
let toggleSystemAliasEditable = system => {
|
||
system.find('.editable').editable('toggle');
|
||
};
|
||
|
||
/**
|
||
* mark system as "selected" e.g. for dragging
|
||
* @param map
|
||
* @param system
|
||
* @param select
|
||
*/
|
||
let setSystemSelect = (map, system, select) => {
|
||
if(select){
|
||
system.addClass(config.systemSelectedClass);
|
||
map.addToDragSelection(system);
|
||
}else{
|
||
system.removeClass(config.systemSelectedClass);
|
||
map.removeFromDragSelection(system);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* mark a system as "active"
|
||
* @param map
|
||
* @param system
|
||
*/
|
||
let setSystemActive = (map, system) => {
|
||
// deselect all selected systems on map
|
||
let mapContainer = map.getContainer();
|
||
[...mapContainer.getElementsByClassName(config.systemClass)]
|
||
.forEach(systemEl =>
|
||
systemEl.classList.remove(config.systemActiveClass)
|
||
);
|
||
|
||
// set current system active
|
||
system.addClass(config.systemActiveClass);
|
||
|
||
// collect all required systemData from map module -> cache
|
||
let systemData = system.getSystemData();
|
||
systemData.mapId = parseInt(system.attr('data-mapid')) || 0;
|
||
Util.setCurrentSystemData(systemData.mapId, systemData);
|
||
};
|
||
|
||
/**
|
||
* set system visibility e.g. or filtered systems
|
||
* @param system
|
||
* @param map
|
||
* @param visible
|
||
*/
|
||
let setSystemVisible = (system, map, visible) => {
|
||
system = $(system);
|
||
if(!visible){
|
||
// invisible systems should no longer be selected
|
||
setSystemSelect(map, system, false);
|
||
}
|
||
system.toggleClass(config.systemHiddenClass, !visible);
|
||
};
|
||
|
||
/**
|
||
* add/remove connection type to connection that was previous registered by registerConnectionTypes()
|
||
* -> this method is a wrapper for addType()/removeType()
|
||
* with the addition of respecting active Arrow overlay direction
|
||
* @param action
|
||
* @param connection
|
||
* @param types
|
||
* @param params
|
||
* @param doNotRepaint
|
||
*/
|
||
let changeConnectionTypes = (action, connection, types = [], params = [], doNotRepaint = false) => {
|
||
|
||
if(connection && types.length){
|
||
// check for active Arrow overlay
|
||
let overlayArrow, overlayArrowParams;
|
||
if(
|
||
!types.includes('info_signature') &&
|
||
connection.hasType('info_signature')
|
||
){
|
||
overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||
if(overlayArrow){
|
||
overlayArrowParams = {
|
||
direction: overlayArrow.direction,
|
||
foldback: overlayArrow.foldback,
|
||
};
|
||
}
|
||
}
|
||
|
||
for(let i = 0; i < types.length; i++){
|
||
// change the new type
|
||
connection[action](types[i], typeof params[i] === 'object' ? params[i] : {}, doNotRepaint);
|
||
}
|
||
|
||
// change Arrow overlay data back to initial direction
|
||
if(
|
||
overlayArrow &&
|
||
(
|
||
overlayArrow.direction !== overlayArrowParams.direction ||
|
||
overlayArrow.foldback !== overlayArrowParams.foldback
|
||
)
|
||
){
|
||
overlayArrow.updateFrom(overlayArrowParams);
|
||
if(!doNotRepaint){
|
||
connection.repaint();
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* add connection type to connection that was previous registered by registerConnectionTypes()
|
||
* @param connection
|
||
* @param type
|
||
* @param params
|
||
* @param doNotRepaint
|
||
*/
|
||
let addConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||
addConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||
};
|
||
|
||
let addConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||
if(connection){
|
||
changeConnectionTypes('addType', connection, types.diff(connection.getType()), params, doNotRepaint);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* remove connection type to connection that was previous registered by registerConnectionTypes()
|
||
* @param connection
|
||
* @param type
|
||
* @param params
|
||
* @param doNotRepaint
|
||
*/
|
||
let removeConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||
removeConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||
};
|
||
|
||
let removeConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||
if(connection){
|
||
changeConnectionTypes('removeType', connection, types.intersect(connection.getType()), params, doNotRepaint);
|
||
}
|
||
};
|
||
|
||
let toggleConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||
changeConnectionTypes('toggleType', connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||
};
|
||
|
||
/**
|
||
* mark a connection as "active"
|
||
* @param map
|
||
* @param connections
|
||
*/
|
||
let setConnectionsActive = (map, connections) => {
|
||
map.setSuspendDrawing(true);
|
||
|
||
// set all inactive
|
||
for(let connection of getConnectionsByType(map, 'state_active')){
|
||
if(!connections.includes(connection)){
|
||
removeConnectionType(connection, 'state_active');
|
||
}
|
||
}
|
||
|
||
for(let connection of connections){
|
||
if(!connection.hasType('state_active')){
|
||
addConnectionType(connection, 'state_active');
|
||
}
|
||
}
|
||
|
||
map.setSuspendDrawing(false, true);
|
||
};
|
||
|
||
/**
|
||
* set connection visibility e.g. for filtered systems
|
||
* @param connection
|
||
* @param visible
|
||
*/
|
||
let setConnectionVisible = (connection, visible) => {
|
||
if(connection.isVisible() !== visible){
|
||
connection.setVisible(visible, true);
|
||
for(let endpoint of connection.endpoints){
|
||
endpoint.setVisible(visible, true);
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* toggle "selected" status of system
|
||
* @param map
|
||
* @param systems
|
||
*/
|
||
let toggleSystemsSelect = (map, systems) => {
|
||
for(let system of systems){
|
||
system = $(system);
|
||
if(system.data('locked') !== true){
|
||
if(system.hasClass(config.systemSelectedClass)){
|
||
setSystemSelect(map, system, false);
|
||
}else{
|
||
setSystemSelect(map, system, true);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* toggle "selected" status of connections
|
||
* @param map
|
||
* @param connections
|
||
*/
|
||
let toggleConnectionActive = (map, connections) => {
|
||
let selectedConnections = [];
|
||
let deselectedConnections = [];
|
||
|
||
map.setSuspendDrawing(true);
|
||
|
||
for(let connection of connections){
|
||
if(connection.hasType('state_active')){
|
||
removeConnectionType(connection, 'state_active');
|
||
deselectedConnections.push(connection);
|
||
}else{
|
||
addConnectionType(connection, 'state_active');
|
||
selectedConnections.push(connection);
|
||
}
|
||
}
|
||
|
||
map.setSuspendDrawing(false, true);
|
||
|
||
updateConnectionInfo(map, selectedConnections, deselectedConnections);
|
||
};
|
||
|
||
/**
|
||
* show global map info panels
|
||
* @param map
|
||
*/
|
||
let showMapInfo = map => {
|
||
// get parent Tab Content and fire update event
|
||
let mapContainer = $(map.getContainer());
|
||
|
||
getTabContentElementByMapElement(mapContainer).trigger('pf:renderGlobalModules', {
|
||
mapId: parseInt(mapContainer.data('id')),
|
||
payload: null
|
||
});
|
||
};
|
||
|
||
/**
|
||
* show system info panels
|
||
* @param map
|
||
* @param system
|
||
*/
|
||
let showSystemInfo = (map, system) => {
|
||
setSystemActive(map, system);
|
||
|
||
// get parent Tab Content and fire update event
|
||
let mapContainer = $(map.getContainer());
|
||
let mapId = parseInt(mapContainer.data('id')) || 0;
|
||
|
||
getTabContentElementByMapElement(mapContainer).trigger('pf:renderSystemModules', {
|
||
mapId: mapId,
|
||
payload: Util.getCurrentSystemData(mapId)
|
||
});
|
||
};
|
||
|
||
/**
|
||
* show connection info panels
|
||
* @param map
|
||
* @param connections
|
||
*/
|
||
let showConnectionInfo = (map, connections) => {
|
||
setConnectionsActive(map, connections);
|
||
|
||
// get parent Tab Content and fire update event
|
||
let mapContainer = $(map.getContainer());
|
||
|
||
getTabContentElementByMapElement(mapContainer).trigger('pf:renderConnectionModules', {
|
||
mapId: parseInt(mapContainer.data('id')),
|
||
payload: connections
|
||
});
|
||
};
|
||
|
||
/**
|
||
* update connection info panels
|
||
* @param map
|
||
* @param selectedConnections
|
||
* @param deselectedConnections
|
||
*/
|
||
let updateConnectionInfo = (map, selectedConnections, deselectedConnections) => {
|
||
// get parent Tab Content and fire update event
|
||
let mapContainer = $(map.getContainer());
|
||
|
||
$(document).trigger('pf:updateConnectionInfoModule', {
|
||
connectionsUpdate: selectedConnections,
|
||
connectionsRemove: deselectedConnections,
|
||
mapId: parseInt(mapContainer.data('id'))
|
||
});
|
||
};
|
||
|
||
/**
|
||
* show "find route" dialog -> trigger route panel
|
||
* @param mapContainer
|
||
* @param systemToData
|
||
*/
|
||
let showFindRouteDialog = (mapContainer, systemToData) => {
|
||
// get parent Tab Content and fire update event
|
||
getTabContentElementByMapElement(mapContainer).trigger('pf:updateRouteModules', {
|
||
mapId: parseInt(mapContainer.data('id')),
|
||
payload: {
|
||
task: 'showFindRouteDialog',
|
||
systemToData: systemToData
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* performs a new route search -> trigger route panel
|
||
* @param mapContainer
|
||
* @param systemToData
|
||
*/
|
||
let findRoute = (mapContainer, systemToData) => {
|
||
getTabContentElementByMapElement(mapContainer).trigger('pf:updateRouteModules', {
|
||
mapId: parseInt(mapContainer.data('id')),
|
||
payload: {
|
||
task: 'findRoute',
|
||
systemToData: systemToData
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* search connections by systems
|
||
* @param map
|
||
* @param systems
|
||
* @param scope
|
||
* @returns {Array}
|
||
*/
|
||
let searchConnectionsBySystems = (map, systems, scope) => {
|
||
let connections = [];
|
||
let withBackConnection = true;
|
||
|
||
$.each(systems, function(i, system){
|
||
// get connections where system is source
|
||
connections = connections.concat( map.getConnections({scope: scope, source: system}) );
|
||
if(withBackConnection === true){
|
||
// get connections where system is target
|
||
connections = connections.concat( map.getConnections({scope: scope, target: system}) );
|
||
}
|
||
});
|
||
return connections;
|
||
};
|
||
|
||
/**
|
||
* search connections by scope and/or type
|
||
* -> scope and target can be an array
|
||
* @param map
|
||
* @param scope
|
||
* @param type
|
||
* @param noHidden
|
||
* @returns {Array}
|
||
*/
|
||
let searchConnectionsByScopeAndType = (map, scope, type = undefined, noHidden = false) => {
|
||
let connections = [];
|
||
let scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
|
||
let typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
|
||
|
||
map.select({scope: scopeArray}).each(function(connection){
|
||
if(noHidden && !connection.isVisible()){
|
||
// exclude invisible connection
|
||
return;
|
||
}
|
||
|
||
if(typeArray.length > 0){
|
||
// filter by connection type as well...
|
||
for(let i = 0; i < typeArray.length; i++){
|
||
if( connection.hasType(typeArray[i]) ){
|
||
connections.push(connection);
|
||
break; // don´t add same connection multiple times
|
||
}
|
||
}
|
||
}else{
|
||
// connection type is ignored
|
||
connections.push(connection);
|
||
}
|
||
});
|
||
|
||
return connections;
|
||
};
|
||
|
||
/**
|
||
* get Connection Info by option
|
||
* @param {string} connectionTyp
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getConnectionInfo = (connectionTyp, option) => {
|
||
let connectionInfo = '';
|
||
if(Init.connectionTypes.hasOwnProperty(connectionTyp)){
|
||
connectionInfo = Init.connectionTypes[connectionTyp][option];
|
||
}
|
||
return connectionInfo;
|
||
};
|
||
|
||
/**
|
||
* get CSS classes for connection types
|
||
* @param types
|
||
* @returns {string[]}
|
||
*/
|
||
let getConnectionFakeClassesByTypes = types => {
|
||
let connectionClasses = ['pf-fake-connection'];
|
||
for(let i = 0; i < types.length; i++){
|
||
connectionClasses.push(getConnectionInfo(types[i], 'cssClass'));
|
||
}
|
||
return connectionClasses;
|
||
};
|
||
|
||
/**
|
||
* get all direct connections between two given systems
|
||
* @param map
|
||
* @param systemA
|
||
* @param systemB
|
||
* @returns {*[]}
|
||
*/
|
||
let checkForConnection = (map, systemA, systemB) => {
|
||
let connections = [];
|
||
connections = connections.concat( map.getConnections({scope: '*', source: systemA, target: systemB}) );
|
||
// get connections where system is target
|
||
connections = connections.concat( map.getConnections({scope: '*', source: systemB, target: systemA}) );
|
||
return connections;
|
||
};
|
||
|
||
/**
|
||
* get the default connection type for a scope
|
||
* e.g. for new type after scope change
|
||
* @param {string} scope
|
||
* @returns {string}
|
||
*/
|
||
let getDefaultConnectionTypeByScope = scope => {
|
||
let type = '';
|
||
switch(scope){
|
||
case 'wh':
|
||
type = 'wh_fresh'; break;
|
||
case 'jumpbridge':
|
||
type = 'jumpbridge'; break;
|
||
case'stargate':
|
||
type = 'stargate'; break;
|
||
case'abyssal':
|
||
type = 'abyssal'; break;
|
||
default:
|
||
console.error('Connection scope "' + scope + '" unknown!');
|
||
}
|
||
|
||
return type;
|
||
};
|
||
|
||
/**
|
||
* get all available connection types for "mass status"
|
||
* @returns {string[]}
|
||
*/
|
||
let allConnectionMassStatusTypes = () => {
|
||
return ['wh_fresh', 'wh_reduced', 'wh_critical'];
|
||
};
|
||
|
||
/**
|
||
* get all available connection types for "jump mass size"
|
||
* @returns {string[]}
|
||
*/
|
||
let allConnectionJumpMassTypes = () => {
|
||
return ['wh_jump_mass_s', 'wh_jump_mass_m', 'wh_jump_mass_l', 'wh_jump_mass_xl'];
|
||
};
|
||
|
||
/**
|
||
* set/change/remove connection mass status of connection
|
||
* -> statusType == undefined will remove (all) existing mass status types
|
||
* @param connection
|
||
* @param statusType
|
||
*/
|
||
let setConnectionMassStatusType = (connection, statusType) => {
|
||
setUniqueConnectionType(connection, statusType, allConnectionMassStatusTypes());
|
||
|
||
};
|
||
|
||
/**
|
||
* set/change/remove connection jump mass of a connection
|
||
* -> massType == undefined will remove (all) existing jump mass types
|
||
* @param connection
|
||
* @param massType
|
||
*/
|
||
let setConnectionJumpMassType = (connection, massType) => {
|
||
setUniqueConnectionType(connection, massType, allConnectionJumpMassTypes());
|
||
};
|
||
|
||
/**
|
||
* set/change/remove connection type
|
||
* -> type == undefined will remove (all) existing provided types
|
||
* @param connection
|
||
* @param type
|
||
* @param types
|
||
*/
|
||
let setUniqueConnectionType = (connection, type, types) => {
|
||
type = types.includes(type) ? [type] : [];
|
||
|
||
connection._jsPlumb.instance.setSuspendDrawing(true);
|
||
|
||
// ... redraw should be suspended (no repaint until function ends)
|
||
let doNotRepaint = connection._jsPlumb.instance.isSuspendDrawing();
|
||
removeConnectionTypes(connection, types.diff(type), [], doNotRepaint);
|
||
addConnectionTypes(connection, type, [], doNotRepaint);
|
||
|
||
connection._jsPlumb.instance.setSuspendDrawing(false, true);
|
||
};
|
||
|
||
/**
|
||
* get some scope info for a given info string
|
||
* @param {string} info
|
||
* @param {string} option
|
||
* @returns {string}
|
||
*/
|
||
let getScopeInfoForConnection = (info, option) => {
|
||
let scopeInfo = '';
|
||
if(Init.connectionScopes.hasOwnProperty(info)){
|
||
switch(option){
|
||
case 'connectorDefinition':
|
||
// json data in DB
|
||
let temp = '{ "data": ' + Init.connectionScopes[info][option] + '}';
|
||
scopeInfo = $.parseJSON( temp).data;
|
||
break;
|
||
default:
|
||
scopeInfo = Init.connectionScopes[info][option];
|
||
break;
|
||
}
|
||
}
|
||
|
||
return scopeInfo;
|
||
};
|
||
|
||
/**
|
||
* show map animations when a new map gets visual
|
||
* @param mapElement
|
||
* @param show
|
||
* @returns {Promise<any>}
|
||
*/
|
||
let visualizeMap = (mapElement, show) => {
|
||
|
||
let visualizeMapExecutor = (resolve, reject) => {
|
||
// start map update counter -> prevent map updates during animations
|
||
MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
|
||
|
||
let systemElements = mapElement.find('.' + config.systemClass);
|
||
let endpointElements = mapElement.find('.jtk-endpoint:visible');
|
||
let connectorElements = mapElement.find('.jtk-connector:visible');
|
||
let overlayElements = mapElement.find('.jtk-overlay:visible, .tooltip');
|
||
|
||
let hideElements = (elements) => {
|
||
if(elements.length > 0){
|
||
// disable transition for next opacity change
|
||
elements.addClass('pf-notransition');
|
||
// hide elements
|
||
elements.css('opacity', 0);
|
||
// Trigger a reflow, flushing the CSS changes
|
||
// -> http://stackoverflow.com/questions/11131875/what-is-the-cleanest-way-to-disable-css-transition-effects-temporarily
|
||
elements[0].offsetHeight; // jshint ignore:line
|
||
elements.removeClass('pf-notransition');
|
||
}
|
||
|
||
return elements;
|
||
};
|
||
|
||
let mapElements = systemElements.add(endpointElements).add(connectorElements);
|
||
|
||
// show nice animation
|
||
if(show === 'show'){
|
||
hideElements(systemElements);
|
||
hideElements(endpointElements);
|
||
hideElements(connectorElements);
|
||
hideElements(overlayElements);
|
||
|
||
overlayElements.velocity('transition.fadeIn', {
|
||
duration: 60,
|
||
display: 'auto'
|
||
});
|
||
|
||
if(mapElements.length){
|
||
mapElements.velocity({
|
||
translateY: [ 0, -20],
|
||
opacity: [ 1, 0 ]
|
||
}, {
|
||
duration: 150,
|
||
easing: 'easeOut',
|
||
complete: function(){
|
||
resolve({
|
||
action: 'visualizeMap',
|
||
data: false
|
||
});
|
||
}
|
||
});
|
||
}else{
|
||
// "complete" callback is not fired if no elements were animated
|
||
resolve({
|
||
action: 'visualizeMap',
|
||
data: false
|
||
});
|
||
}
|
||
|
||
}else if(show === 'hide'){
|
||
|
||
overlayElements.velocity('transition.fadeOut', {
|
||
duration: 60,
|
||
display: 'auto'
|
||
});
|
||
|
||
if(mapElements.length){
|
||
mapElements.velocity({
|
||
translateY: [ -20, 0 ],
|
||
opacity: [ 0, 1 ]
|
||
}, {
|
||
duration: 150,
|
||
easing: 'easeOut',
|
||
complete: function(){
|
||
resolve({
|
||
action: 'visualizeMap',
|
||
data: false
|
||
});
|
||
}
|
||
});
|
||
}else{
|
||
// "complete" callback is not fired if no elements were animated
|
||
resolve({
|
||
action: 'visualizeMap',
|
||
data: false
|
||
});
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
return new Promise(visualizeMapExecutor);
|
||
};
|
||
|
||
/**
|
||
* Set default map options (from right menu)
|
||
* This function is called only ONCE per map after create!
|
||
* -> HINT: This function triggers events! Promise is resolved before trigger callback finishes
|
||
* @param mapElement
|
||
* @param mapConfig
|
||
* @returns {Promise<any>}
|
||
*/
|
||
let setMapDefaultOptions = (mapElement, mapConfig) => {
|
||
|
||
let setMapDefaultOptionsExecutor = (resolve, reject) => {
|
||
// update main menu options based on the active map -----------------------------------------------
|
||
$(document).trigger('pf:updateMenuOptions', {
|
||
menuGroup: 'mapOptions',
|
||
payload: mapConfig
|
||
});
|
||
|
||
// init grid snap ---------------------------------------------------------------------------------
|
||
Util.triggerMenuAction(mapElement, 'MapOption', {
|
||
option: 'mapSnapToGrid',
|
||
toggle: false
|
||
});
|
||
|
||
// init magnetizer --------------------------------------------------------------------------------
|
||
Util.triggerMenuAction(mapElement, 'MapOption', {
|
||
option: 'mapMagnetizer',
|
||
toggle: false
|
||
});
|
||
|
||
// init compact system layout ---------------------------------------------------------------------
|
||
Util.triggerMenuAction(mapElement, 'MapOption', {
|
||
option: 'systemRegion',
|
||
toggle: false
|
||
});
|
||
|
||
// init compact system layout ---------------------------------------------------------------------
|
||
Util.triggerMenuAction(mapElement, 'MapOption', {
|
||
option: 'systemCompact',
|
||
toggle: false
|
||
});
|
||
|
||
// init endpoint overlay --------------------------------------------------------------------------
|
||
Util.triggerMenuAction(mapElement, 'MapOption', {
|
||
option: 'connectionSignatureOverlays',
|
||
toggle: false,
|
||
skipOnEnable: true, // skip callback -> Otherwise it would run 2 times on map create
|
||
skipOnDisable: true // skip callback -> Otherwise it would run 2 times on map create
|
||
});
|
||
|
||
resolve({
|
||
action: 'setMapDefaultOptions',
|
||
data: false
|
||
});
|
||
};
|
||
|
||
return new Promise(setMapDefaultOptionsExecutor);
|
||
};
|
||
|
||
/**
|
||
* get system coordinates from systemElement
|
||
* @param system
|
||
* @returns {{x: number, y: number}}
|
||
*/
|
||
let getSystemPosition = system => {
|
||
let x = system.css('left');
|
||
let y = system.css('top');
|
||
|
||
return {
|
||
x: parseInt(x.substring(0, x.length - 2)),
|
||
y: parseInt(y.substring(0, y.length - 2))
|
||
};
|
||
};
|
||
|
||
/**
|
||
* scroll map to default (stored) x/y coordinates
|
||
* @param map
|
||
* @returns {Promise<any>}
|
||
*/
|
||
let scrollToDefaultPosition = map => {
|
||
|
||
let scrollToDefaultPositionExecutor = resolve => {
|
||
let payload = {
|
||
action: 'scrollToDefaultPosition',
|
||
data: false
|
||
};
|
||
|
||
// no map scroll on zoomed maps -> scrollbar offset on zoomed maps does not work properly
|
||
// -> implementation would be difficult...
|
||
if(map.getZoom() === 1){
|
||
let mapElement = $(map.getContainer());
|
||
Util.getLocalStore('map').getItem(mapElement.data('id')).then(data => {
|
||
if(data && data.scrollOffset){
|
||
let areaMap = mapElement.closest('.' + Util.getMapTabContentAreaClass('map'));
|
||
Scrollbar.scrollToPosition(areaMap, [data.scrollOffset.y, data.scrollOffset.x]);
|
||
}
|
||
|
||
resolve(payload);
|
||
});
|
||
}else{
|
||
resolve(payload);
|
||
}
|
||
};
|
||
|
||
return new Promise(scrollToDefaultPositionExecutor);
|
||
};
|
||
|
||
/**
|
||
* zoom map to default (stored) scale()
|
||
* @param map
|
||
* @returns {Promise<any>}
|
||
*/
|
||
let zoomToDefaultScale = map => {
|
||
|
||
let zoomToDefaultScaleExecutor = resolve => {
|
||
let mapElement = $(map.getContainer());
|
||
Util.getLocalStore('map').getItem(mapElement.data('id')).then(data => {
|
||
if(data && data.mapZoom){
|
||
setZoom(map, data.mapZoom);
|
||
}
|
||
|
||
resolve({
|
||
action: 'zoomToDefaultScale',
|
||
data: false
|
||
});
|
||
});
|
||
};
|
||
|
||
return new Promise(zoomToDefaultScaleExecutor);
|
||
};
|
||
|
||
/**
|
||
* set or change rallyPoint for systems
|
||
* @param rallyUpdated
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.setSystemRally = function(rallyUpdated, options){
|
||
rallyUpdated = rallyUpdated || 0;
|
||
let rallyPoke = false;
|
||
|
||
let defaultOptions = {
|
||
poke: false,
|
||
hideNotification: false, // do not show notification
|
||
hideCounter: false // do not start map update counter
|
||
};
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
return this.each(function(){
|
||
let system = $(this);
|
||
let rally = system.data('rallyUpdated') || 0;
|
||
|
||
if(rallyUpdated !== rally){
|
||
// rally status changed
|
||
if( !options.hideCounter ){
|
||
MapOverlayUtil.getMapOverlay(system, 'timer').startMapUpdateCounter();
|
||
}
|
||
|
||
let rallyClass = getInfoForSystem('rally', 'class');
|
||
|
||
if(rallyUpdated > 0){
|
||
// new rally point set OR update system with rally information
|
||
system.addClass(rallyClass);
|
||
|
||
// rallyUpdated > 0 is required for poke!
|
||
rallyPoke = options.poke;
|
||
|
||
let notificationOptions = {
|
||
title: 'Rally Point',
|
||
text: 'System: ' + system.data('name')
|
||
};
|
||
|
||
if(rallyUpdated === 1){
|
||
// rally point not saved on DB
|
||
notificationOptions.type = 'success';
|
||
Util.showNotify(notificationOptions);
|
||
}else if(options.poke){
|
||
// rally saved AND poke option active
|
||
|
||
// check if desktop notification was already send
|
||
let mapId = system.data('mapid');
|
||
let systemId = system.data('id');
|
||
Util.getLocalStore('map').getItem(mapId).then(function(data){
|
||
// This code runs once the value has been loaded
|
||
// from the offline store.
|
||
let rallyPokeData = {};
|
||
|
||
if(
|
||
data &&
|
||
data.rallyPoke
|
||
){
|
||
// poke data exists
|
||
rallyPokeData = data.rallyPoke;
|
||
}
|
||
|
||
if(
|
||
!rallyPokeData.hasOwnProperty(this.systemId) || // rally poke was not already send to client
|
||
rallyPokeData[this.systemId] !== rallyUpdated // already send to that system but in the past
|
||
){
|
||
rallyPokeData[this.systemId] = rallyUpdated;
|
||
Util.getLocalStore('map').setItem(`${this.mapId}.rallyPoke`, rallyPokeData);
|
||
|
||
notificationOptions.type = 'info';
|
||
Util.showNotify(notificationOptions, {
|
||
desktop: true,
|
||
stack: 'barBottom',
|
||
click: e => {window.location.href = getMapDeeplinkUrl(mapId, systemId);}
|
||
});
|
||
}
|
||
}.bind({
|
||
mapId: mapId,
|
||
systemId: systemId,
|
||
rallyUpdated: rallyUpdated
|
||
}));
|
||
}
|
||
|
||
// update active "route" module -> add rally point row --------------------------------------------
|
||
let mapContainer = system.parents('.' + Util.config.mapClass);
|
||
findRoute(mapContainer, {
|
||
systemId: system.data('systemId'),
|
||
name: system.data('name'),
|
||
rally: 1
|
||
});
|
||
}else{
|
||
// rally point removed
|
||
system.removeClass(rallyClass);
|
||
|
||
if( !options.hideNotification ){
|
||
Util.showNotify({title: 'Rally point removed', type: 'success'});
|
||
}
|
||
}
|
||
}
|
||
|
||
system.data('rallyUpdated', rallyUpdated);
|
||
system.data('rallyPoke', rallyPoke);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* set map "shortcut" events
|
||
*/
|
||
$.fn.setMapShortcuts = function(){
|
||
return this.each((i, areaMap) => {
|
||
areaMap = $(areaMap);
|
||
let mapElement = areaMap.find('.' + Util.config.mapClass);
|
||
|
||
// dynamic require Map module -> otherwise there is a require(), loop
|
||
let Map = require('app/map/map');
|
||
let System = require('app/map/system');
|
||
let map = Map.getMapInstance(mapElement.data('id'));
|
||
|
||
areaMap.watchKey('mapSystemAdd', areaMap => {
|
||
System.showNewSystemDialog(map, {position: {x: 0, y: 0}}, Map.saveSystemCallback);
|
||
},{focus: true});
|
||
|
||
areaMap.watchKey('mapSystemsSelect', areaMap => {
|
||
mapElement.selectAllSystems();
|
||
},{focus: true});
|
||
|
||
areaMap.watchKey('mapSystemsDelete', areaMap => {
|
||
let selectedSystems = mapElement.getSelectedSystems();
|
||
$.fn.showDeleteSystemDialog(map, selectedSystems);
|
||
},{focus: true});
|
||
});
|
||
};
|
||
|
||
/**
|
||
* add system pilot tooltip
|
||
* @param systemUserData
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.addSystemPilotTooltip = function(systemUserData, options){
|
||
let content = Util.getSystemPilotsTable(systemUserData);
|
||
|
||
let defaultOptions = {
|
||
placement: 'top',
|
||
html: true,
|
||
trigger: 'hover',
|
||
container: 'body',
|
||
title: 'Pilots',
|
||
content: content,
|
||
delay: {
|
||
show: 150,
|
||
hide: 0
|
||
},
|
||
};
|
||
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
return this.each(function(){
|
||
$(this).popover(options);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* add station services tooltip
|
||
* @param services
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.addStationServiceTooltip = function(services, options){
|
||
let getServiceIcon = service => {
|
||
switch(service){
|
||
case 'bounty-missions': return false;
|
||
case 'assasination-missions': return false;
|
||
case 'courier-missions': return false;
|
||
case 'interbus': return false;
|
||
case 'reprocessing-plant': return 'reprocess';
|
||
case 'refinery': return false;
|
||
case 'market': return 'market';
|
||
case 'black-market': return false;
|
||
case 'stock-exchange': return false;
|
||
case 'cloning': return 'clonebay';
|
||
case 'surgery': return false;
|
||
case 'dna-therapy': return false;
|
||
case 'repair-facilities': return 'repairshop';
|
||
case 'factory': return 'industry';
|
||
case 'labratory': return 'research';
|
||
case 'gambling': return false;
|
||
case 'fitting': return 'fitting';
|
||
case 'paintshop': return 'skins';
|
||
case 'news': return false;
|
||
case 'storage': return false;
|
||
case 'insurance': return 'insurance';
|
||
case 'docking': return 'docking';
|
||
case 'office-rental': return false;
|
||
case 'jump-clone-facility': return 'jumpclones';
|
||
case 'loyalty-point-store': return 'lpstore';
|
||
case 'navy-offices': return 'factionalwarfare';
|
||
case 'security-offices': return 'concord';
|
||
default: return false;
|
||
}
|
||
};
|
||
|
||
let getStationServicesTable = services => {
|
||
let content = '';
|
||
for(let i = 0; i < services.length; i++){
|
||
let icon = getServiceIcon(services[i]);
|
||
if(icon){
|
||
content += `<img class="${Util.config.popoverListIconClass}" src="${Util.imgRoot()}icons/client/ui/window/${icon}.png" alt="${services[i]}">`;
|
||
}
|
||
}
|
||
return content;
|
||
};
|
||
|
||
let content = getStationServicesTable(services);
|
||
|
||
let title = '<i class="fas fa-tools fa-fw"></i> Services';
|
||
|
||
let defaultOptions = {
|
||
placement: 'top',
|
||
html: true,
|
||
trigger: 'hover',
|
||
container: 'body',
|
||
title: title,
|
||
content: '',
|
||
delay: {
|
||
show: 150,
|
||
hide: 0
|
||
},
|
||
};
|
||
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
return this.each(function(){
|
||
let element = $(this);
|
||
element.popover(options);
|
||
|
||
// set new popover content
|
||
let popover = element.data('bs.popover');
|
||
popover.options.content = content;
|
||
popover.tip().addClass(Util.config.popoverClass);
|
||
|
||
if(options.show){
|
||
element.popover('show');
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* add system effect tooltip
|
||
* @param security
|
||
* @param effect
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.addSystemEffectTooltip = function(security, effect, options){
|
||
let effectClass = getEffectInfoForSystem(effect, 'class');
|
||
let systemEffectData = Util.getSystemEffectData(security, effect);
|
||
let areaId = Util.getAreaIdBySecurity(security);
|
||
|
||
let title = '<i class="fas fa-square fa-fw ' + effectClass + '"></i> ' +
|
||
getEffectInfoForSystem(effect, 'name') + ' ' +
|
||
'<kbd>' + Util.getSystemEffectMultiplierByAreaId(parseInt(areaId)) + 'x' + '</kbd>' +
|
||
'<span class="pull-right ' + Util.getSecurityClassForSystem(security) + '">' + security + '</span>';
|
||
|
||
let content = Util.getSystemEffectTable(systemEffectData);
|
||
|
||
let defaultOptions = {
|
||
placement: 'top',
|
||
html: true,
|
||
trigger: 'hover',
|
||
container: 'body',
|
||
title: title,
|
||
content: content,
|
||
delay: {
|
||
show: 150,
|
||
hide: 0
|
||
},
|
||
};
|
||
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
return this.each(function(){
|
||
$(this).popover(options);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* add system planets tooltip
|
||
* @param planets
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.addSystemPlanetsTooltip = function(planets, options){
|
||
let content = Util.getSystemPlanetsTable(planets);
|
||
|
||
let defaultOptions = {
|
||
placement: 'top',
|
||
html: true,
|
||
trigger: 'hover',
|
||
container: 'body',
|
||
title: 'Planets',
|
||
content: content,
|
||
delay: {
|
||
show: 150,
|
||
hide: 0
|
||
},
|
||
};
|
||
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
return this.each(function(){
|
||
if(!planets) return
|
||
if(planets.length){
|
||
// Abyss systems don´t have planets -> no tooltip
|
||
let element = $(this);
|
||
element.popover(options);
|
||
|
||
if(options.show){
|
||
element.popover('show');
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* add a wormhole tooltip with wh specific data to elements
|
||
* @param tooltipData
|
||
* @param options
|
||
* @returns {*}
|
||
*/
|
||
$.fn.addWormholeInfoTooltip = function(tooltipData, options){
|
||
return this.each(function(){
|
||
let element = $(this);
|
||
|
||
requirejs(['text!templates/tooltip/wormhole_info.html', 'mustache'], (template, Mustache) => {
|
||
|
||
// format tooltip data
|
||
let data = {};
|
||
if(tooltipData.massTotal){
|
||
data.massTotal = Util.formatMassValue(tooltipData.massTotal);
|
||
}else{
|
||
data.massTotal = '<span class="txt-color txt-color-grayLight">unknown</span>';
|
||
}
|
||
if(tooltipData.massIndividual){
|
||
data.massIndividual = Util.formatMassValue(tooltipData.massIndividual);
|
||
}else{
|
||
data.massIndividual = '<span class="txt-color txt-color-grayLight">unknown</span>';
|
||
}
|
||
if(tooltipData.massRegeneration){
|
||
data.massRegeneration = Util.formatMassValue(tooltipData.massRegeneration);
|
||
}
|
||
if(tooltipData.maxStableTime){
|
||
data.maxStableTime = tooltipData.maxStableTime + ' h';
|
||
}
|
||
if(tooltipData.scanWormholeStrength){
|
||
data.scanWormholeStrength = parseFloat(tooltipData.scanWormholeStrength).toLocaleString() + ' %';
|
||
}else{
|
||
data.scanWormholeStrength = '<span class="txt-color txt-color-grayLight">unknown</span>';
|
||
}
|
||
|
||
let title = tooltipData.name;
|
||
|
||
if(tooltipData.size){
|
||
title += ' <kbd>' + tooltipData.size.label + '</kbd>';
|
||
}
|
||
|
||
if(tooltipData.security){
|
||
// K162 has no security
|
||
title += '<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>';
|
||
}
|
||
|
||
let content = Mustache.render(template, data);
|
||
|
||
let defaultOptions = {
|
||
placement: 'top',
|
||
html: true,
|
||
trigger: 'hover',
|
||
container: 'body',
|
||
title: title,
|
||
content: '',
|
||
delay: {
|
||
show: 150,
|
||
hide: 0
|
||
}
|
||
};
|
||
|
||
options = $.extend({}, defaultOptions, options);
|
||
|
||
element.popover(options);
|
||
|
||
// set new popover content
|
||
let popover = element.data('bs.popover');
|
||
popover.options.title = title;
|
||
popover.options.content = content;
|
||
|
||
if(options.smaller){
|
||
element.setPopoverSmall();
|
||
}
|
||
|
||
if(options.show){
|
||
element.popover('show');
|
||
}
|
||
});
|
||
});
|
||
};
|
||
|
||
/**
|
||
*
|
||
* @param container any parent element that holds the event
|
||
* @param selector element that bubbles up hover
|
||
* @param options tooltip options
|
||
*/
|
||
let initWormholeInfoTooltip = (container, selector, options = {}) => {
|
||
let defaultOptions = {
|
||
trigger: 'manual',
|
||
placement: 'top',
|
||
smaller: false,
|
||
show: true
|
||
};
|
||
|
||
options = Object.assign({}, defaultOptions, options);
|
||
|
||
container.hoverIntent({
|
||
over: function(e){
|
||
let staticWormholeElement = $(this);
|
||
let wormholeName = staticWormholeElement.attr('data-name');
|
||
let wormholeData = Util.getObjVal(Init, 'wormholes.' + wormholeName);
|
||
if(wormholeData){
|
||
staticWormholeElement.addWormholeInfoTooltip(wormholeData, options);
|
||
}
|
||
},
|
||
out: function(e){
|
||
$(this).destroyPopover();
|
||
},
|
||
selector: selector
|
||
});
|
||
};
|
||
|
||
/**
|
||
* get systemId string (selector
|
||
* @param mapId
|
||
* @param systemId
|
||
* @returns {string}
|
||
*/
|
||
let getSystemId = (mapId, systemId) => {
|
||
return config.systemIdPrefix + mapId + '-' + systemId;
|
||
};
|
||
|
||
/**
|
||
* check whether the current User has access for a given right
|
||
* based on a given mapConfig
|
||
* @param right
|
||
* @param mapConfig
|
||
* @returns {boolean}
|
||
*/
|
||
let checkRight = (right, mapConfig) => {
|
||
let hasAccess = false;
|
||
let mapType = Util.getObjVal(mapConfig, 'type.name');
|
||
let accessObjectId = Util.getCurrentUserInfo(mapType + 'Id');
|
||
|
||
// check whether character has map access
|
||
let mapAccess = Util.getObjVal(mapConfig, 'access.' + (mapType === 'private' ? 'character' : mapType)) || [];
|
||
let hasMapAccess = mapAccess.some(accessObj => accessObj.id === accessObjectId);
|
||
if(hasMapAccess){
|
||
// ... this should ALWAYS be be true!
|
||
switch(mapType){
|
||
case 'private':
|
||
hasAccess = true;
|
||
break;
|
||
case 'corporation':
|
||
hasAccess = Util.hasRight(right, mapType);
|
||
break;
|
||
case 'alliance':
|
||
hasAccess = true;
|
||
break;
|
||
}
|
||
}
|
||
return hasAccess;
|
||
};
|
||
|
||
/**
|
||
*
|
||
* @param options
|
||
* @param maxResults
|
||
* @param findChain
|
||
* @returns {Array}
|
||
*/
|
||
let findNonOverlappingDimensions = (options = {}, maxResults = 1, findChain = false) => {
|
||
let defaultOptions = {
|
||
center: [0, 30],
|
||
loops: 4,
|
||
debug: false
|
||
};
|
||
|
||
options = Object.assign({}, defaultOptions, options);
|
||
let positionFinder = new Layout.Position(Object.assign({}, defaultOptions, options));
|
||
|
||
return positionFinder.findNonOverlappingDimensions(maxResults, findChain);
|
||
};
|
||
|
||
/**
|
||
* calculate the x/y coordinates for a new system - relative to a source system
|
||
* @param sourceSystem
|
||
* @returns {Array}
|
||
*/
|
||
let newSystemPositionBySystem = sourceSystem => {
|
||
let mapContainer = sourceSystem.parent();
|
||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||
|
||
let options = {
|
||
container: mapContainer[0],
|
||
center: sourceSystem[0],
|
||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false
|
||
};
|
||
|
||
return findNonOverlappingDimensions(options);
|
||
};
|
||
|
||
/**
|
||
* calculate the x/y coordinates for a new system - relative to x/y position
|
||
* @param mapContainer
|
||
* @param options
|
||
* @param maxResults
|
||
* @param findChain
|
||
* @returns {Array}
|
||
*/
|
||
let newSystemPositionByCoordinates = (mapContainer, options = {}, maxResults = 1, findChain = false) => {
|
||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||
|
||
let defaultOptions = {
|
||
container: mapContainer[0],
|
||
center: [0, 0],
|
||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false,
|
||
loops: 10,
|
||
defaultGapX: 10,
|
||
defaultGapY: 10,
|
||
//debugOk: true,
|
||
//debug: true
|
||
};
|
||
|
||
options = Object.assign({}, defaultOptions, options);
|
||
|
||
return findNonOverlappingDimensions(options, maxResults, findChain);
|
||
};
|
||
|
||
/**
|
||
* calculate the x/y coordinates for a new system - relative to current map scroll offset
|
||
* @param mapContainer
|
||
* @param maxResults
|
||
* @returns {[{x: number, y: number}]}
|
||
*/
|
||
let newSystemPositionsByMapOffset = (mapContainer, maxResults = 1) => {
|
||
let scrollPosition = {
|
||
x: Math.abs(parseInt(mapContainer.attr('data-scroll-left')) || 0),
|
||
y: Math.abs(parseInt(mapContainer.attr('data-scroll-top')) || 0)
|
||
};
|
||
|
||
// space new positions from map top (e.g. used for tooltips)
|
||
scrollPosition.y = Math.max(scrollPosition.y, 30);
|
||
|
||
// default position -> current map section top/left
|
||
let positions = [scrollPosition];
|
||
|
||
// check default position for overlapping
|
||
let dimensions = newSystemPositionByCoordinates(mapContainer, {
|
||
center: [scrollPosition.x, scrollPosition.y],
|
||
minX: scrollPosition.x,
|
||
minY: scrollPosition.y
|
||
}, maxResults, true);
|
||
|
||
if(dimensions.length){
|
||
positions = dimensions.map(dim => ({
|
||
x: parseInt(dim.left) || 0,
|
||
y: parseInt(dim.top) || 0
|
||
}));
|
||
}
|
||
return positions;
|
||
};
|
||
|
||
/**
|
||
*
|
||
* @param mapContainer
|
||
*/
|
||
let newSystemPositionsByMap = mapContainer => {
|
||
let positions = {};
|
||
|
||
if(mapContainer){
|
||
let mapId = mapContainer.data('id');
|
||
|
||
positions.defaults = newSystemPositionsByMapOffset(mapContainer, 2);
|
||
|
||
// -> calc possible coordinates for new system that should be used based on current user location ---------
|
||
let currentLocationData = Util.getCurrentLocationData();
|
||
if(currentLocationData.id){
|
||
// ... we need to the PF systemId for 'SelectSystem' trigger
|
||
let systemData = getSystemData(mapId, currentLocationData.id, 'systemId');
|
||
if(systemData){
|
||
let currentSystem = $('#' + getSystemId(mapId, systemData.id));
|
||
if(currentSystem.length){
|
||
let dimensions = newSystemPositionBySystem(currentSystem);
|
||
if(dimensions.length){
|
||
//... empty map space found
|
||
positions.location = {
|
||
systemId: currentLocationData.id,
|
||
position: {
|
||
x: dimensions[0].left,
|
||
y: dimensions[0].top
|
||
}
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return Object.keys(positions).length ? positions : null;
|
||
};
|
||
|
||
/**
|
||
* get a unique map url for deeplinking
|
||
* @param mapId
|
||
* @param systemId
|
||
* @returns {string}
|
||
*/
|
||
let getMapDeeplinkUrl = (mapId, systemId) => {
|
||
let url = location.protocol + '//' + location.host + '/map';
|
||
url += mapId ? '/' + encodeURIComponent(window.btoa(mapId)) : '';
|
||
url += systemId ? '_' + encodeURIComponent(window.btoa(systemId)) : '';
|
||
return url;
|
||
};
|
||
|
||
return {
|
||
config: config,
|
||
setMapInstance: setMapInstance,
|
||
getMapInstance: getMapInstance,
|
||
existsMapInstance: existsMapInstance,
|
||
clearMapInstance: clearMapInstance,
|
||
getMapTypes: getMapTypes,
|
||
getMapScopes: getMapScopes,
|
||
getScopeInfoForMap: getScopeInfoForMap,
|
||
getMapIcons: getMapIcons,
|
||
getInfoForMap: getInfoForMap,
|
||
getInfoForSystem: getInfoForSystem,
|
||
getSystemDataFromMapData: getSystemDataFromMapData,
|
||
getSystemData: getSystemData,
|
||
getConnectionDataFromMapData: getConnectionDataFromMapData,
|
||
getConnectionData: getConnectionData,
|
||
getSystemTypeInfo: getSystemTypeInfo,
|
||
getEffectInfoForSystem: getEffectInfoForSystem,
|
||
markAsChanged: markAsChanged,
|
||
hasChanged: hasChanged,
|
||
toggleSystemsSelect: toggleSystemsSelect,
|
||
addConnectionTypes: addConnectionTypes,
|
||
removeConnectionTypes: removeConnectionTypes,
|
||
toggleConnectionType: toggleConnectionType,
|
||
toggleConnectionActive: toggleConnectionActive,
|
||
setSystemActive: setSystemActive,
|
||
showMapInfo: showMapInfo,
|
||
showSystemInfo: showSystemInfo,
|
||
showConnectionInfo: showConnectionInfo,
|
||
showFindRouteDialog: showFindRouteDialog,
|
||
filterDefaultTypes: filterDefaultTypes,
|
||
getEndpointLabel: getEndpointLabel,
|
||
getConnectionsByType: getConnectionsByType,
|
||
getEndpointsDataByConnection: getEndpointsDataByConnection,
|
||
getDataByConnection: getDataByConnection,
|
||
getDataByConnections: getDataByConnections,
|
||
searchConnectionsBySystems: searchConnectionsBySystems,
|
||
searchConnectionsByScopeAndType: searchConnectionsByScopeAndType,
|
||
getConnectionInfo: getConnectionInfo,
|
||
getConnectionFakeClassesByTypes: getConnectionFakeClassesByTypes,
|
||
checkForConnection: checkForConnection,
|
||
getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope,
|
||
allConnectionMassStatusTypes: allConnectionMassStatusTypes,
|
||
allConnectionJumpMassTypes: allConnectionJumpMassTypes,
|
||
setConnectionMassStatusType: setConnectionMassStatusType,
|
||
setConnectionJumpMassType: setConnectionJumpMassType,
|
||
getScopeInfoForConnection: getScopeInfoForConnection,
|
||
deleteConnections: deleteConnections,
|
||
getConnectionDataFromSignatures: getConnectionDataFromSignatures,
|
||
getEndpointOverlaySignatureLocation: getEndpointOverlaySignatureLocation,
|
||
formatEndpointOverlaySignatureLabel: formatEndpointOverlaySignatureLabel,
|
||
getTabContentElementByMapElement: getTabContentElementByMapElement,
|
||
hasActiveConnection: hasActiveConnection,
|
||
filterMapByScopes: filterMapByScopes,
|
||
changeZoom: changeZoom,
|
||
setZoom: setZoom,
|
||
toggleSystemAliasEditable: toggleSystemAliasEditable,
|
||
visualizeMap: visualizeMap,
|
||
setMapDefaultOptions: setMapDefaultOptions,
|
||
getSystemPosition: getSystemPosition,
|
||
scrollToDefaultPosition: scrollToDefaultPosition,
|
||
zoomToDefaultScale: zoomToDefaultScale,
|
||
initWormholeInfoTooltip: initWormholeInfoTooltip,
|
||
getSystemId: getSystemId,
|
||
checkRight: checkRight,
|
||
newSystemPositionBySystem: newSystemPositionBySystem,
|
||
newSystemPositionByCoordinates: newSystemPositionByCoordinates,
|
||
newSystemPositionsByMapOffset: newSystemPositionsByMapOffset,
|
||
newSystemPositionsByMap: newSystemPositionsByMap,
|
||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||
};
|
||
}); |