- new "bubble"-tag for "connection endpoints", closed #301

- new filter option for "bubbled" connections added to "route search" dialog, closed #301
This commit is contained in:
Mark Friedrich
2019-04-27 23:38:52 +02:00
parent f68aebc3de
commit b5a3012ffd
39 changed files with 2337 additions and 1781 deletions

View File

@@ -789,7 +789,7 @@ class Map extends Controller\AccessController {
foreach($connections as $i => $connectionData){
// check if the current connection belongs to the current map
if($connection = $map->getConnectionById((int)$connectionData['id'])){
$connection->copyfrom($connectionData, ['scope', 'type']);
$connection->copyfrom($connectionData, ['scope', 'type', 'endpoints']);
if($connection->save($activeCharacter)){
$mapChanged = true;
// one connection belongs to ONE map -> speed up for multiple maps

View File

@@ -125,6 +125,8 @@ class Route extends Controller\AccessController {
$excludeTypes = [];
$includeEOL = true;
$excludeEndpointTypes = [];
if( $filterData['stargates'] === true){
// include "stargates" for search
$includeScopes[] = 'stargate';
@@ -161,6 +163,10 @@ class Route extends Controller\AccessController {
}
}
if( $filterData['endpointsBubble'] !== true ){
$excludeEndpointTypes[] = 'bubble';
}
// search connections -------------------------------------------------------------------------------------
if( !empty($includeScopes) ){
@@ -178,6 +184,11 @@ class Route extends Controller\AccessController {
$whereQuery .= " `connection`.`eolUpdated` IS NULL AND ";
}
if( !empty($excludeEndpointTypes) ){
$whereQuery .= " CONCAT_WS(' ', `connection`.`sourceEndpointType`, `connection`.`targetEndpointType`) ";
$whereQuery .= " NOT REGEXP '" . implode("|", $excludeEndpointTypes) . "' AND ";
}
$query = "SELECT
`system_src`.`systemId` systemSourceId,
`system_tar`.`systemId` systemTargetId
@@ -717,22 +728,23 @@ class Route extends Controller\AccessController {
// search route with filter options
$filterData = [
'stargates' => (bool) $routeData['stargates'],
'jumpbridges' => (bool) $routeData['jumpbridges'],
'wormholes' => (bool) $routeData['wormholes'],
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
'wormholesFrigate' => (bool) $routeData['wormholesFrigate'],
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
'flag' => $routeData['flag']
'stargates' => (bool) $routeData['stargates'],
'jumpbridges' => (bool) $routeData['jumpbridges'],
'wormholes' => (bool) $routeData['wormholes'],
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
'wormholesFrigate' => (bool) $routeData['wormholesFrigate'],
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
'endpointsBubble' => (bool) $routeData['endpointsBubble'],
'flag' => $routeData['flag']
];
$returnRoutData = [
'systemFromData' => $routeData['systemFromData'],
'systemToData' => $routeData['systemToData'],
'skipSearch' => (bool) $routeData['skipSearch'],
'maps' => $mapData,
'mapIds' => $mapIds
'systemFromData' => $routeData['systemFromData'],
'systemToData' => $routeData['systemToData'],
'skipSearch' => (bool) $routeData['skipSearch'],
'maps' => $mapData,
'mapIds' => $mapIds
];
// add filter options for each route as well
@@ -742,10 +754,10 @@ class Route extends Controller\AccessController {
!$returnRoutData['skipSearch'] &&
count($mapIds) > 0
){
$systemFrom = $routeData['systemFromData']['name'];
$systemFromId = (int)$routeData['systemFromData']['systemId'];
$systemTo = $routeData['systemToData']['name'];
$systemToId = (int)$routeData['systemToData']['systemId'];
$systemFrom = $routeData['systemFromData']['name'];
$systemFromId = (int)$routeData['systemFromData']['systemId'];
$systemTo = $routeData['systemToData']['name'];
$systemToId = (int)$routeData['systemToData']['systemId'];
$cacheKey = $this->getRouteCacheKey(
$mapIds,

View File

@@ -68,6 +68,14 @@ class ConnectionModel extends AbstractMapTrackingModel {
'type' => self::DT_JSON,
'activity-log' => true
],
'sourceEndpointType' => [
'type' => self::DT_JSON,
'activity-log' => true
],
'targetEndpointType' => [
'type' => self::DT_JSON,
'activity-log' => true
],
'eolUpdated' => [
'type' => Schema::DT_TIMESTAMP,
'default' => null
@@ -97,6 +105,10 @@ class ConnectionModel extends AbstractMapTrackingModel {
$connectionData->created = strtotime($this->created);
$connectionData->eolUpdated = strtotime($this->eolUpdated);
if( !empty($endpointsData = $this->getEndpointsData()) ){
$connectionData->endpoints = $endpointsData;
}
if($addSignatureData){
if( !empty($signaturesData = $this->getSignaturesData()) ){
$connectionData->signatures = $signaturesData;
@@ -134,6 +146,33 @@ class ConnectionModel extends AbstractMapTrackingModel {
return $type;
}
/**
* setter for endpoints data (data for source/target endpoint)
* @param $endpointsData
*/
public function set_endpoints($endpointsData){
if(!empty($endpointData = (array)$endpointsData['source'])){
$this->setEndpointData('source', $endpointData);
}
if(!empty($endpointData = (array)$endpointsData['target'])){
$this->setEndpointData('target', $endpointData);
}
}
/**
* set connection endpoint related data
* @param string $label (source||target)
* @param array $endpointData
*/
public function setEndpointData(string $label, array $endpointData = []){
if($this->exists($field = $label . 'EndpointType')){
$types = empty($types = (array)$endpointData['types']) ? null : $types;
if($this->$field != $types){
$this->$field = $types;
}
}
}
/**
* check object for model access
* @param CharacterModel $characterModel
@@ -342,6 +381,38 @@ class ConnectionModel extends AbstractMapTrackingModel {
return $logs;
}
/**
* get endpoint data for $type (source || target)
* @param string $type
* @return array
*/
protected function getEndpointData(string $type) : array {
$endpointData = [];
if($this->exists($field = $type . 'EndpointType') && !empty($types = (array)$this->$field)){
$endpointData['types'] = $types;
}
return $endpointData;
}
/**
* get all endpoint data for this connection
* @return array
*/
protected function getEndpointsData() : array {
$endpointsData = [];
if(!empty($endpointData = $this->getEndpointData('source'))){
$endpointsData['source'] = $endpointData;
}
if(!empty($endpointData = $this->getEndpointData('target'))){
$endpointsData['target'] = $endpointData;
}
return $endpointsData;
}
/**
* get all signature data linked to this connection
* @return array

View File

@@ -316,6 +316,12 @@ define(['jquery'], ($) => {
},
// map scopes
defaultMapScope: 'wh', // default scope for connection
// map endpoint types
endpointTypes: {
bubble: {
cssClass: 'pf-map-endpoint-bubble',
}
},
// map connection types
connectionTypes: {
abyssal: {

View File

@@ -213,20 +213,6 @@ define([
.addClass('text-content')
.attr('imgTitle', obj.title);
let moduleConfig = {
name: obj.href, // template name
position: newSlideContent,
functions: {
after: function(){
// element inserted -> load complete
callback({
type: 'complete',
target: newSlideContent[0]
});
}
}
};
// render HTML file (template)
let moduleData = {
id: config.headHeaderMapId,
@@ -236,7 +222,9 @@ define([
mapBgImageId: config.mapBgImageId
};
Render.showModule(moduleConfig, moduleData);
Render.render(obj.href, moduleData)
.then(payload => newSlideContent.append(payload))
.then(payload => callback({type: 'complete', target: payload[0]}));
return newSlideContent[0];
};

View File

@@ -10,146 +10,58 @@ define([
'use strict';
let config = {
dynamicElementWrapperId: 'pf-dialog-wrapper', // wrapper div for context menus (initial hidden)
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
systemContextMenuId: 'pf-map-system-contextmenu' // id for "systems" context menu
};
$.fn.contextMenu = function(settings){
// animation
let animationInType = 'transition.flipXIn';
let animationInDuration = 150;
let animationOutType = 'transition.flipXOut';
let animationOutDuration = 150;
return this.each(function(){
// Open context menu
$(this).off('pf:openContextMenu').on('pf:openContextMenu', function(e, originalEvent, component, hiddenOptions, activeOptions, disabledOptions){
// hide all other open context menus
$('#pf-dialog-wrapper > .dropdown-menu').hide();
let contextMenu = $(settings.menuSelector);
let menuLiElements = contextMenu.find('li');
// reset all menu entries
menuLiElements.removeClass('active').removeClass('disabled').show();
// hide specific menu entries
for(let action of hiddenOptions){
contextMenu.find('li[data-action="' + action + '"]').hide();
}
//set active specific menu entries
for(let action of activeOptions){
contextMenu.find('li[data-action="' + action + '"]').addClass('active');
}
//disable specific menu entries
for(let action of disabledOptions){
contextMenu.find('li[data-action="' + action + '"]').addClass('disabled');
}
//open menu
contextMenu.css({
position: 'absolute',
left: getLeftLocation(originalEvent),
top: getTopLocation(originalEvent)
}).velocity(animationInType, {
duration: animationInDuration,
complete: function(){
let posX = 0;
let posY = 0;
if(
originalEvent.offsetX &&
originalEvent.offsetY
){
// Chrome
posX = originalEvent.offsetX;
posY = originalEvent.offsetY;
}else if(originalEvent.originalEvent){
// Firefox -> #415
posX = originalEvent.originalEvent.layerX;
posY = originalEvent.originalEvent.layerY;
}
let position = {
x: posX,
y: posY
};
$(this).off('click').one('click', {component: component, position: position}, function(e){
// hide contextmenu
$(this).hide();
let params = {
selectedMenu: $(e.target),
component: e.data.component,
position: e.data.position
};
settings.menuSelected.call(this, params);
return false;
});
}
});
//make sure menu closes on any click
$(document).one('click.closeContextmenu', function(){
$('.dropdown-menu[role="menu"]').velocity(animationOutType, {
duration: animationOutDuration
});
});
return false;
});
});
function getLeftLocation(e){
let mouseWidth = e.pageX;
let pageWidth = $(window).width();
let menuWidth = $(settings.menuSelector).width();
// opening menu would pass the side of the page
if(mouseWidth + menuWidth > pageWidth &&
menuWidth < mouseWidth){
return mouseWidth - menuWidth;
}
return mouseWidth;
}
function getTopLocation(e){
let mouseHeight = e.pageY;
let pageHeight = $(window).height();
let menuHeight = $(settings.menuSelector).height();
// opening menu would pass the bottom of the page
if(mouseHeight + menuHeight > pageHeight &&
menuHeight < mouseHeight){
return mouseHeight - menuHeight;
}
return mouseHeight;
}
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
endpointContextMenuId: 'pf-map-endpoint-contextmenu', // id for "endpoints" context menu
systemContextMenuId: 'pf-map-system-contextmenu', // id for "systems" context menu
animationInType: 'transition.flipXIn',
animationInDuration: 150,
animationOutType: 'transition.flipXOut',
animationOutDuration: 150
};
/**
* load context menu template for maps
* calc menu X coordinate
* @param e
* @param menuWidth
* @returns {number|*}
*/
let initMapContextMenu = () => {
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let getMenuLeftCoordinate = (e, menuWidth) => {
let mouseWidth = e.pageX;
let pageWidth = $(window).width();
// opening menu would pass the side of the page
if(mouseWidth + menuWidth > pageWidth &&
menuWidth < mouseWidth){
return mouseWidth - menuWidth;
}
return mouseWidth;
};
/**
* calc menu Y coordinate
* @param e
* @param menuHeight
* @returns {number|*}
*/
let getMenuTopCoordinate = (e, menuHeight) => {
let mouseHeight = e.pageY;
let pageHeight = $(window).height();
// opening menu would pass the bottom of the page
if(mouseHeight + menuHeight > pageHeight &&
menuHeight < mouseHeight){
return mouseHeight - menuHeight;
}
return mouseHeight;
};
/**
* render context menu template for maps
* @returns {*}
*/
let renderMapContextMenu = () => {
let moduleData = {
id: config.mapContextMenuId,
items: [
@@ -170,18 +82,14 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* load context menu template for connections
* render context menu template for connections
* @returns {*}
*/
let initConnectionContextMenu = () => {
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let renderConnectionContextMenu = () => {
let moduleData = {
id: config.connectionContextMenuId,
items: [
@@ -206,15 +114,30 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* load context menu template for systems
* @param systemStatusData
* render context menu template for endpoints
* @returns {*}
*/
let initSystemContextMenu = (systemStatusData) => {
let renderEndpointContextMenu = () => {
let moduleData = {
id: config.endpointContextMenuId,
items: [
{icon: 'fa-globe', action: 'bubble', text: 'bubbled'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* render context menu template for systems
* @param systemStatusData
* @returns {*}
*/
let renderSystemContextMenu = systemStatusData => {
let statusData = [];
for(let [statusName, data] of Object.entries(systemStatusData)){
statusData.push({
@@ -225,11 +148,6 @@ define([
});
}
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let moduleData = {
id: config.systemContextMenuId,
items: [
@@ -250,12 +168,132 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* prepare (hide/activate/disable) some menu options
* @param menuElement
* @param hiddenOptions
* @param activeOptions
* @param disabledOptions
* @returns {*}
*/
let prepareMenu = (menuElement, hiddenOptions, activeOptions, disabledOptions) => {
let menuLiElements = menuElement.find('li');
// reset all menu entries
menuLiElements.removeClass('active').removeClass('disabled').show();
// hide specific menu entries
for(let action of hiddenOptions){
menuElement.find('li[data-action="' + action + '"]').hide();
}
//set active specific menu entries
for(let action of activeOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('active');
}
//disable specific menu entries
for(let action of disabledOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('disabled');
}
return menuElement;
};
/**
* close all context menus (map, connection,...)
* @param excludeMenu
*/
let closeMenus = excludeMenu => {
let allMenus = $('.dropdown-menu[role="menu"]');
if(excludeMenu){
allMenus = allMenus.not(excludeMenu);
}
allMenus.velocity(config.animationOutType, {
duration: config.animationOutDuration
});
};
/**
* open menu handler
* @param menuConfig
* @param e
* @param context
*/
let openMenu = (menuConfig, e, context) => {
let menuElement = $('#' + menuConfig.id);
// close all other context menus
closeMenus(menuElement);
// remove menu list click event
// -> required in case the close handler could not remove them properly
// -> this happens if menu re-opens without closing (2x right click)
menuElement.off('click', 'li');
// hide/activate/disable
menuElement = prepareMenu(menuElement, menuConfig.hidden, menuConfig.active, menuConfig.disabled);
menuElement.css({
position: 'absolute',
left: getMenuLeftCoordinate(e, menuElement.width()),
top: getMenuTopCoordinate(e, menuElement.height())
}).velocity(config.animationInType, {
duration: config.animationInDuration,
complete: function(){
context = {
original: {
event: e,
context: context,
},
selectCallback: menuConfig.selectCallback
};
$(this).one('click', 'li', context, selectHandler);
}
});
};
/**
* menu item select handler
* @param e
*/
let selectHandler = e => {
if(e.data.selectCallback){
e.data.selectCallback(
$(e.currentTarget).attr('data-action'),
e.data.original.context.component,
e.data.original.event
);
}
};
/**
* default config (skeleton) for valid context menu configuration
* @returns {{hidden: Array, active: Array, disabled: Array, id: string, selectCallback: null}}
*/
let defaultMenuOptionConfig = () => {
return {
'id': '',
'selectCallback': null,
'hidden': [],
'active': [],
'disabled': []
};
};
return {
initMapContextMenu: initMapContextMenu,
initConnectionContextMenu: initConnectionContextMenu,
initSystemContextMenu: initSystemContextMenu
config: config,
defaultMenuOptionConfig: defaultMenuOptionConfig,
renderMapContextMenu: renderMapContextMenu,
renderConnectionContextMenu: renderConnectionContextMenu,
renderEndpointContextMenu: renderEndpointContextMenu,
renderSystemContextMenu: renderSystemContextMenu,
openMenu: openMenu,
closeMenus: closeMenus
};
});

View File

@@ -394,7 +394,30 @@ define(() => {
}
}
/**
* return mouse coordinates from event
* @param e
* @returns {{x: number, y: number}}
*/
let getEventCoordinates = e => {
let posX = 0;
let posY = 0;
if(e.offsetX && e.offsetY){
// Chrome
posX = e.offsetX;
posY = e.offsetY;
}else if(e.originalEvent){
// Firefox -> #415
posX = e.originalEvent.layerX;
posY = e.originalEvent.layerY;
}
return {x: posX, y: posY};
};
return {
Position: Position
Position: Position,
getEventCoordinates: getEventCoordinates
};
});

File diff suppressed because it is too large Load Diff

View File

@@ -283,6 +283,26 @@ define([
return mapElement.find('.' + config.systemSelectedClass);
};
let filterDefaultTypes = types => {
return types.filter(type => type.length > 0 && type !== 'default' && type !== 'active');
};
/**
* returns "target/source" label from endpoint
* @param endpoint
* @returns {string}
*/
let getLabelByEndpoint = endpoint => {
return endpoint.isSource ? 'source' : endpoint.isTarget ? 'target' : false;
};
let getDataByEndpoint = endpoint => {
return {
label: getLabelByEndpoint(endpoint),
types: filterDefaultTypes(endpoint.getType())
};
};
/**
* filter connections by type
* @param map
@@ -304,37 +324,38 @@ define([
/**
* get all relevant data for a connection object
* @param connection
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
* @returns {{targetName: *, endpoints, scope: *, targetAlias: *, id: number, source: number, sourceName: *, type, updated: number, sourceAlias: *, target: number}}
*/
let getDataByConnection = (connection) => {
let getDataByConnection = connection => {
let source = $(connection.source);
let target = $(connection.target);
let id = connection.getParameter('connectionId');
let updated = connection.getParameter('updated');
let connectionTypes = connection.getType();
let endpoints = {source: {}, target: {}};
for(let endpoint of connection.endpoints){
let endpointData = getDataByEndpoint(endpoint);
if(endpointData.label === 'source'){
endpoints.source = endpointData;
}else if(endpointData.label === 'target'){
endpoints.target = endpointData;
}
}
// normalize connection array
connectionTypes = $.grep(connectionTypes, function(n){
// 'default' is added by jsPlumb by default -_-
return ( n.length > 0 && n !== 'default' && n !== 'active');
});
let data = {
return {
id: id ? id : 0,
source: parseInt( source.data('id') ),
source: parseInt(source.data('id')),
sourceName: source.data('name'),
sourceAlias: source.getSystemInfo(['alias']) || source.data('name'),
target: parseInt( target.data('id') ),
target: parseInt(target.data('id')),
targetName: target.data('name'),
targetAlias: target.getSystemInfo(['alias']) || target.data('name'),
scope: connection.scope,
type: connectionTypes,
type: filterDefaultTypes(connection.getType()),
endpoints: endpoints,
updated: updated ? updated : 0
};
return data;
};
/**
@@ -342,7 +363,7 @@ define([
* @param connections
* @returns {Array}
*/
let getDataByConnections = (connections) => {
let getDataByConnections = connections => {
let data = [];
for(let connection of connections){
data.push(getDataByConnection(connection));
@@ -430,7 +451,6 @@ define([
){
let SystemSignatures = require('app/ui/module/system_signature');
let connectionId = connection.getParameter('connectionId');
let sourceEndpoint = connection.endpoints[0];
let targetEndpoint = connection.endpoints[1];
let sourceSystem = $(sourceEndpoint.element);
@@ -1704,6 +1724,7 @@ define([
showSystemInfo: showSystemInfo,
showConnectionInfo: showConnectionInfo,
showFindRouteDialog: showFindRouteDialog,
getLabelByEndpoint: getLabelByEndpoint,
getConnectionsByType: getConnectionsByType,
getDataByConnection: getDataByConnection,
searchConnectionsBySystems: searchConnectionsBySystems,

View File

@@ -209,7 +209,7 @@ define([
Page.initTabChangeObserver();
// init hidden context menu elements
Page.initMapContextMenus();
Page.renderMapContextMenus();
// init map module
mapModule.initMapModule();
@@ -415,7 +415,7 @@ define([
// map update done, init new trigger
// get the current update delay (this can change if a user is inactive)
let mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
let mapUpdateDelay = Util.getCurrentTriggerDelay(logKeyServerMapData, 0);
// init new trigger
initMapUpdatePing(false);

View File

@@ -749,6 +749,11 @@ define([
.select2('destroy');
});
// global "close" trigger for context menus
documentElement.on('click', function(){
MapContextMenu.closeMenus();
});
// disable menu links based on current map config
documentElement.on('pf:updateMenuOptions', function(e, data){
let hasRightMapDelete = MapUtil.checkRight('map_delete', data.mapConfig);
@@ -1181,12 +1186,15 @@ define([
/**
* add "hidden" context menu elements to page
*/
let initMapContextMenus = () => {
$('#' + config.dynamicElementWrapperId).append(
MapContextMenu.initMapContextMenu(),
MapContextMenu.initConnectionContextMenu(),
MapContextMenu.initSystemContextMenu(Init.systemStatus)
);
let renderMapContextMenus = () => {
Promise.all([
MapContextMenu.renderMapContextMenu(),
MapContextMenu.renderConnectionContextMenu(),
MapContextMenu.renderEndpointContextMenu(),
MapContextMenu.renderSystemContextMenu(Init.systemStatus)
]).then(payloads => {
$('#' + config.dynamicElementWrapperId).append(payloads.join(''));
});
};
/**
@@ -1315,7 +1323,7 @@ define([
return {
initTabChangeObserver: initTabChangeObserver,
initMapContextMenus: initMapContextMenus
renderMapContextMenus: renderMapContextMenus
};
});

View File

@@ -2,59 +2,23 @@
* Render controller
*/
define(['jquery', 'mustache'], function($, Mustache){
define(['jquery', 'mustache'], ($, Mustache) => {
'use strict';
/**
* init function will be called before and after a new module is loaded
* @param functionName
* @param config
*/
let initModule = function(functionName, config){
if(
typeof config.functions === 'object' &&
typeof config.functions[functionName] === 'function'
){
config.functions[functionName](config);
}
};
/**
* load a template and render is with Mustache
* @param config
* render Mustache template
* @param path
* @param data
* @returns {Promise<any>}
*/
let showModule = function(config, data){
// require module template
requirejs(['text!templates/' + config.name + '.html'], function(template){
// check for an id, if module already exists, do not insert again
if(
data.id === 'undefined' ||
$('#' + data.id).length === 0
){
let content = Mustache.render(template, data);
// display module
switch(config.link){
case 'prepend':
config.position.prepend(content);
break;
case 'before':
config.position.before(content);
break;
case 'after':
config.position.after(content);
break;
default:
config.position.append(content);
}
}
// init module function after render
initModule('after', config);
});
let render = (path, data) => {
let renderExecutor = (resolve) => {
requirejs(['text!templates/' + path + '.html'], template => {
resolve(Mustache.render(template, data));
});
};
return new Promise(renderExecutor);
};
/**
@@ -180,7 +144,7 @@ define(['jquery', 'mustache'], function($, Mustache){
};
return {
showModule: showModule,
render: render,
highlightJson: highlightJson
};
});

View File

@@ -200,7 +200,7 @@ define([
let mapUrl = $(this).find('span').text().trim();
Util.copyToClipboard(mapUrl).then(payload => {
if(payload.data){
Util.showNotify({title: 'Copied to clipbaord', text: mapUrl, type: 'success'});
Util.showNotify({title: 'Copied to clipboard', text: mapUrl, type: 'success'});
}
});
});
@@ -1155,26 +1155,33 @@ define([
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// unset formatted string (to much content)
if(cellData.formatted){
// clone data before delete() values
cellData = Object.assign({}, cellData);
delete(cellData.formatted);
}
$(cell).on('mouseenter', function(e){
let cell = $(this);
if(!cell.data('bs.popover')){
if(cellData.formatted){
// clone data before delete() values
cellData = Object.assign({}, cellData);
delete(cellData.formatted);
}
let jsonHighlighted = Render.highlightJson(cellData);
let content = '<pre><code>' + jsonHighlighted + '</code></pre>';
let jsonHighlighted = Render.highlightJson(cellData);
let content = '<pre><code>' + jsonHighlighted + '</code></pre>';
// open popover with raw log data
$(cell).popover({
placement: 'left',
html: true,
trigger: 'hover',
content: content,
container: 'body',
title: 'Raw data',
delay: {
show: 180,
hide: 0
// open popover with raw log data
cell.popover({
placement: 'left',
html: true,
trigger: 'hover',
content: content,
container: 'body',
title: 'Raw data',
delay: {
show: 180,
hide: 0
}
});
cell.popover('show');
}
});
}

View File

@@ -232,6 +232,7 @@ define([
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
endpointsBubble: (rowData.hasOwnProperty('endpointsBubble')) ? rowData.endpointsBubble | 0 : 1,
connections: (rowData.hasOwnProperty('connections')) ? rowData.connections.value | 0 : 0,
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
};
@@ -324,7 +325,8 @@ define([
wormholesReduced: routeDialogData.hasOwnProperty('wormholesReduced') ? parseInt(routeDialogData.wormholesReduced) : 0,
wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt(routeDialogData.wormholesCritical) : 0,
wormholesFrigate: routeDialogData.hasOwnProperty('wormholesFrigate') ? parseInt(routeDialogData.wormholesFrigate) : 0,
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt(routeDialogData.wormholesEOL) : 0
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt(routeDialogData.wormholesEOL) : 0,
endpointsBubble: routeDialogData.hasOwnProperty('endpointsBubble') ? parseInt(routeDialogData.endpointsBubble) : 0
}]
};
@@ -731,7 +733,7 @@ define([
// button class for flag (e.g. "secure" routes)
let flagButtonClass = routeData.flag === 'secure' ? 'txt-color-success' : '';
let connectionButton = '<i class="fas ' + ['fa-link', 'txt-color'].join(' ') + '"></i>';
let connectionButton = '<i class="fas ' + ['fa-code-branch', 'fa-rotate-270', 'txt-color'].join(' ') + '"></i>';
let flagButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', flagButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fas ' + ['fa-sync'].join(' ') + '"></i>';
let searchButton = '<i class="fas ' + ['fa-search'].join(' ') + '"></i>';
@@ -760,6 +762,7 @@ define([
wormholesCritical: routeData.wormholesCritical,
wormholesFrigate: routeData.wormholesFrigate,
wormholesEOL: routeData.wormholesEOL,
endpointsBubble: routeData.endpointsBubble,
connections: {
value: 0,
button: connectionButton
@@ -994,7 +997,7 @@ define([
}
},{
targets: 5,
title: '<i title="toggle connections" data-toggle="tooltip" class="fas fa-link text-right"></i>',
title: '<i title="toggle connections" data-toggle="tooltip" class="fas fa-code-branch fa-rotate-270 text-right"></i>',
orderable: false,
searchable: false,
width: 10,

View File

@@ -2933,7 +2933,7 @@ define([
};
/**
* check an element for attached event by name
* check an element for attached jQuery event by name
* -> e.g. eventName = 'click.myNamespace'
* @param element
* @param eventName
@@ -2941,22 +2941,25 @@ define([
*/
let hasEvent = (element, eventName) => {
let exists = false;
let parts = eventName.split('.');
let name = parts[0];
let namespace = parts.length === 2 ? parts[1] : false;
let events = $._data( element[0], 'events')[name];
if(events){
if(namespace){
// seach events by namespace
for(let event of events){
if(event.namespace === namespace){
exists = true;
break;
let allEvents = $._data(element[0], 'events');
if(allEvents){
let parts = eventName.split('.');
let name = parts[0];
let events = allEvents[name];
if(events){
let namespace = parts.length === 2 ? parts[1] : false;
if(namespace){
// search events by namespace
for(let event of events){
if(event.namespace === namespace){
exists = true;
break;
}
}
}else{
// at least ONE event of the given name found
exists = true;
}
}else{
// at least ONE event of the given name found
exists = true;
}
}
return exists;

View File

@@ -10388,7 +10388,8 @@
// in IE the top left corner is what it placed at the desired location. This will not
// be fixed. IE8 is not going to be supported for much longer.
var ts = "translate(-50%, calc(-50% - .5px))";
//var ts = "translate(-50%, -50%)";
var ts = "translate3d(-8px, 5px, 0)";
div.style.webkitTransform = ts;
div.style.mozTransform = ts;
div.style.msTransform = ts;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

36
public/img/bubble.svg Normal file
View File

@@ -0,0 +1,36 @@
<?xml version='1.0' encoding='UTF-8'?>
<svg class='y' viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'>
<linearGradient id='g' y1='100%'>
<stop stop-color='#c8b847' offset='0'/>
<stop stop-color='#5cb85c' offset='.5'/>
<stop stop-color='#c8b847' offset='1'/>
</linearGradient>
<radialGradient id='f' fx='25%' fy='25%'>
<stop offset='0'/>
<stop stop-opacity='.2' offset='.3'/>
<stop stop-color='#fff' stop-opacity='.4' offset='.97'/>
<stop offset='1'/>
</radialGradient>
<mask id='e'>
<rect width='100%' height='100%' fill='url(#f)'/>
</mask>
<radialGradient id='a' fy='20%'>
<stop stop-color='#fff' stop-opacity='.7' offset='.1'/>
<stop stop-color='#fff' stop-opacity='0' offset='.7'/>
</radialGradient>
<radialGradient id='b' fy='10%'>
<stop stop-opacity='0' offset='.6'/>
<stop stop-color='#fff' stop-opacity='.25' offset='.9'/>
<stop offset='1'/>
</radialGradient>
<mask id='d'>
<rect width='100%' height='100%' fill='url(#b)'/>
</mask>
<mask id='c'>
<rect transform='rotate(180 50 50)' width='100%' height='100%' fill='url(#b)'/>
</mask>
<ellipse transform='rotate(-45 55 55)' cx='55' cy='55' rx='55' ry='25' fill='url(#a)'></ellipse>
<circle cx='50%' cy='50%' r='50%' fill='#4f9e4f' mask='url(#d)'></circle>
<ellipse transform='rotate(135 150 150)' cx='150' cy='150' rx='40' ry='20' fill='url(#a)'></ellipse>
<circle cx='50%' cy='50%' r='50%' fill='url(#g)' mask='url(#e)'></circle>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -316,6 +316,12 @@ define(['jquery'], ($) => {
},
// map scopes
defaultMapScope: 'wh', // default scope for connection
// map endpoint types
endpointTypes: {
bubble: {
cssClass: 'pf-map-endpoint-bubble',
}
},
// map connection types
connectionTypes: {
abyssal: {

View File

@@ -213,20 +213,6 @@ define([
.addClass('text-content')
.attr('imgTitle', obj.title);
let moduleConfig = {
name: obj.href, // template name
position: newSlideContent,
functions: {
after: function(){
// element inserted -> load complete
callback({
type: 'complete',
target: newSlideContent[0]
});
}
}
};
// render HTML file (template)
let moduleData = {
id: config.headHeaderMapId,
@@ -236,7 +222,9 @@ define([
mapBgImageId: config.mapBgImageId
};
Render.showModule(moduleConfig, moduleData);
Render.render(obj.href, moduleData)
.then(payload => newSlideContent.append(payload))
.then(payload => callback({type: 'complete', target: payload[0]}));
return newSlideContent[0];
};

View File

@@ -10,146 +10,58 @@ define([
'use strict';
let config = {
dynamicElementWrapperId: 'pf-dialog-wrapper', // wrapper div for context menus (initial hidden)
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
systemContextMenuId: 'pf-map-system-contextmenu' // id for "systems" context menu
};
$.fn.contextMenu = function(settings){
// animation
let animationInType = 'transition.flipXIn';
let animationInDuration = 150;
let animationOutType = 'transition.flipXOut';
let animationOutDuration = 150;
return this.each(function(){
// Open context menu
$(this).off('pf:openContextMenu').on('pf:openContextMenu', function(e, originalEvent, component, hiddenOptions, activeOptions, disabledOptions){
// hide all other open context menus
$('#pf-dialog-wrapper > .dropdown-menu').hide();
let contextMenu = $(settings.menuSelector);
let menuLiElements = contextMenu.find('li');
// reset all menu entries
menuLiElements.removeClass('active').removeClass('disabled').show();
// hide specific menu entries
for(let action of hiddenOptions){
contextMenu.find('li[data-action="' + action + '"]').hide();
}
//set active specific menu entries
for(let action of activeOptions){
contextMenu.find('li[data-action="' + action + '"]').addClass('active');
}
//disable specific menu entries
for(let action of disabledOptions){
contextMenu.find('li[data-action="' + action + '"]').addClass('disabled');
}
//open menu
contextMenu.css({
position: 'absolute',
left: getLeftLocation(originalEvent),
top: getTopLocation(originalEvent)
}).velocity(animationInType, {
duration: animationInDuration,
complete: function(){
let posX = 0;
let posY = 0;
if(
originalEvent.offsetX &&
originalEvent.offsetY
){
// Chrome
posX = originalEvent.offsetX;
posY = originalEvent.offsetY;
}else if(originalEvent.originalEvent){
// Firefox -> #415
posX = originalEvent.originalEvent.layerX;
posY = originalEvent.originalEvent.layerY;
}
let position = {
x: posX,
y: posY
};
$(this).off('click').one('click', {component: component, position: position}, function(e){
// hide contextmenu
$(this).hide();
let params = {
selectedMenu: $(e.target),
component: e.data.component,
position: e.data.position
};
settings.menuSelected.call(this, params);
return false;
});
}
});
//make sure menu closes on any click
$(document).one('click.closeContextmenu', function(){
$('.dropdown-menu[role="menu"]').velocity(animationOutType, {
duration: animationOutDuration
});
});
return false;
});
});
function getLeftLocation(e){
let mouseWidth = e.pageX;
let pageWidth = $(window).width();
let menuWidth = $(settings.menuSelector).width();
// opening menu would pass the side of the page
if(mouseWidth + menuWidth > pageWidth &&
menuWidth < mouseWidth){
return mouseWidth - menuWidth;
}
return mouseWidth;
}
function getTopLocation(e){
let mouseHeight = e.pageY;
let pageHeight = $(window).height();
let menuHeight = $(settings.menuSelector).height();
// opening menu would pass the bottom of the page
if(mouseHeight + menuHeight > pageHeight &&
menuHeight < mouseHeight){
return mouseHeight - menuHeight;
}
return mouseHeight;
}
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
endpointContextMenuId: 'pf-map-endpoint-contextmenu', // id for "endpoints" context menu
systemContextMenuId: 'pf-map-system-contextmenu', // id for "systems" context menu
animationInType: 'transition.flipXIn',
animationInDuration: 150,
animationOutType: 'transition.flipXOut',
animationOutDuration: 150
};
/**
* load context menu template for maps
* calc menu X coordinate
* @param e
* @param menuWidth
* @returns {number|*}
*/
let initMapContextMenu = () => {
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let getMenuLeftCoordinate = (e, menuWidth) => {
let mouseWidth = e.pageX;
let pageWidth = $(window).width();
// opening menu would pass the side of the page
if(mouseWidth + menuWidth > pageWidth &&
menuWidth < mouseWidth){
return mouseWidth - menuWidth;
}
return mouseWidth;
};
/**
* calc menu Y coordinate
* @param e
* @param menuHeight
* @returns {number|*}
*/
let getMenuTopCoordinate = (e, menuHeight) => {
let mouseHeight = e.pageY;
let pageHeight = $(window).height();
// opening menu would pass the bottom of the page
if(mouseHeight + menuHeight > pageHeight &&
menuHeight < mouseHeight){
return mouseHeight - menuHeight;
}
return mouseHeight;
};
/**
* render context menu template for maps
* @returns {*}
*/
let renderMapContextMenu = () => {
let moduleData = {
id: config.mapContextMenuId,
items: [
@@ -170,18 +82,14 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* load context menu template for connections
* render context menu template for connections
* @returns {*}
*/
let initConnectionContextMenu = () => {
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let renderConnectionContextMenu = () => {
let moduleData = {
id: config.connectionContextMenuId,
items: [
@@ -206,15 +114,30 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* load context menu template for systems
* @param systemStatusData
* render context menu template for endpoints
* @returns {*}
*/
let initSystemContextMenu = (systemStatusData) => {
let renderEndpointContextMenu = () => {
let moduleData = {
id: config.endpointContextMenuId,
items: [
{icon: 'fa-globe', action: 'bubble', text: 'bubbled'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* render context menu template for systems
* @param systemStatusData
* @returns {*}
*/
let renderSystemContextMenu = systemStatusData => {
let statusData = [];
for(let [statusName, data] of Object.entries(systemStatusData)){
statusData.push({
@@ -225,11 +148,6 @@ define([
});
}
let moduleConfig = {
name: 'modules/contextmenu',
position: $('#' + config.dynamicElementWrapperId)
};
let moduleData = {
id: config.systemContextMenuId,
items: [
@@ -250,12 +168,132 @@ define([
]
};
Render.showModule(moduleConfig, moduleData);
return Render.render('modules/contextmenu', moduleData);
};
/**
* prepare (hide/activate/disable) some menu options
* @param menuElement
* @param hiddenOptions
* @param activeOptions
* @param disabledOptions
* @returns {*}
*/
let prepareMenu = (menuElement, hiddenOptions, activeOptions, disabledOptions) => {
let menuLiElements = menuElement.find('li');
// reset all menu entries
menuLiElements.removeClass('active').removeClass('disabled').show();
// hide specific menu entries
for(let action of hiddenOptions){
menuElement.find('li[data-action="' + action + '"]').hide();
}
//set active specific menu entries
for(let action of activeOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('active');
}
//disable specific menu entries
for(let action of disabledOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('disabled');
}
return menuElement;
};
/**
* close all context menus (map, connection,...)
* @param excludeMenu
*/
let closeMenus = excludeMenu => {
let allMenus = $('.dropdown-menu[role="menu"]');
if(excludeMenu){
allMenus = allMenus.not(excludeMenu);
}
allMenus.velocity(config.animationOutType, {
duration: config.animationOutDuration
});
};
/**
* open menu handler
* @param menuConfig
* @param e
* @param context
*/
let openMenu = (menuConfig, e, context) => {
let menuElement = $('#' + menuConfig.id);
// close all other context menus
closeMenus(menuElement);
// remove menu list click event
// -> required in case the close handler could not remove them properly
// -> this happens if menu re-opens without closing (2x right click)
menuElement.off('click', 'li');
// hide/activate/disable
menuElement = prepareMenu(menuElement, menuConfig.hidden, menuConfig.active, menuConfig.disabled);
menuElement.css({
position: 'absolute',
left: getMenuLeftCoordinate(e, menuElement.width()),
top: getMenuTopCoordinate(e, menuElement.height())
}).velocity(config.animationInType, {
duration: config.animationInDuration,
complete: function(){
context = {
original: {
event: e,
context: context,
},
selectCallback: menuConfig.selectCallback
};
$(this).one('click', 'li', context, selectHandler);
}
});
};
/**
* menu item select handler
* @param e
*/
let selectHandler = e => {
if(e.data.selectCallback){
e.data.selectCallback(
$(e.currentTarget).attr('data-action'),
e.data.original.context.component,
e.data.original.event
);
}
};
/**
* default config (skeleton) for valid context menu configuration
* @returns {{hidden: Array, active: Array, disabled: Array, id: string, selectCallback: null}}
*/
let defaultMenuOptionConfig = () => {
return {
'id': '',
'selectCallback': null,
'hidden': [],
'active': [],
'disabled': []
};
};
return {
initMapContextMenu: initMapContextMenu,
initConnectionContextMenu: initConnectionContextMenu,
initSystemContextMenu: initSystemContextMenu
config: config,
defaultMenuOptionConfig: defaultMenuOptionConfig,
renderMapContextMenu: renderMapContextMenu,
renderConnectionContextMenu: renderConnectionContextMenu,
renderEndpointContextMenu: renderEndpointContextMenu,
renderSystemContextMenu: renderSystemContextMenu,
openMenu: openMenu,
closeMenus: closeMenus
};
});

View File

@@ -394,7 +394,30 @@ define(() => {
}
}
/**
* return mouse coordinates from event
* @param e
* @returns {{x: number, y: number}}
*/
let getEventCoordinates = e => {
let posX = 0;
let posY = 0;
if(e.offsetX && e.offsetY){
// Chrome
posX = e.offsetX;
posY = e.offsetY;
}else if(e.originalEvent){
// Firefox -> #415
posX = e.originalEvent.layerX;
posY = e.originalEvent.layerY;
}
return {x: posX, y: posY};
};
return {
Position: Position
Position: Position,
getEventCoordinates: getEventCoordinates
};
});

File diff suppressed because it is too large Load Diff

View File

@@ -283,6 +283,26 @@ define([
return mapElement.find('.' + config.systemSelectedClass);
};
let filterDefaultTypes = types => {
return types.filter(type => type.length > 0 && type !== 'default' && type !== 'active');
};
/**
* returns "target/source" label from endpoint
* @param endpoint
* @returns {string}
*/
let getLabelByEndpoint = endpoint => {
return endpoint.isSource ? 'source' : endpoint.isTarget ? 'target' : false;
};
let getDataByEndpoint = endpoint => {
return {
label: getLabelByEndpoint(endpoint),
types: filterDefaultTypes(endpoint.getType())
};
};
/**
* filter connections by type
* @param map
@@ -304,37 +324,38 @@ define([
/**
* get all relevant data for a connection object
* @param connection
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
* @returns {{targetName: *, endpoints, scope: *, targetAlias: *, id: number, source: number, sourceName: *, type, updated: number, sourceAlias: *, target: number}}
*/
let getDataByConnection = (connection) => {
let getDataByConnection = connection => {
let source = $(connection.source);
let target = $(connection.target);
let id = connection.getParameter('connectionId');
let updated = connection.getParameter('updated');
let connectionTypes = connection.getType();
let endpoints = {source: {}, target: {}};
for(let endpoint of connection.endpoints){
let endpointData = getDataByEndpoint(endpoint);
if(endpointData.label === 'source'){
endpoints.source = endpointData;
}else if(endpointData.label === 'target'){
endpoints.target = endpointData;
}
}
// normalize connection array
connectionTypes = $.grep(connectionTypes, function(n){
// 'default' is added by jsPlumb by default -_-
return ( n.length > 0 && n !== 'default' && n !== 'active');
});
let data = {
return {
id: id ? id : 0,
source: parseInt( source.data('id') ),
source: parseInt(source.data('id')),
sourceName: source.data('name'),
sourceAlias: source.getSystemInfo(['alias']) || source.data('name'),
target: parseInt( target.data('id') ),
target: parseInt(target.data('id')),
targetName: target.data('name'),
targetAlias: target.getSystemInfo(['alias']) || target.data('name'),
scope: connection.scope,
type: connectionTypes,
type: filterDefaultTypes(connection.getType()),
endpoints: endpoints,
updated: updated ? updated : 0
};
return data;
};
/**
@@ -342,7 +363,7 @@ define([
* @param connections
* @returns {Array}
*/
let getDataByConnections = (connections) => {
let getDataByConnections = connections => {
let data = [];
for(let connection of connections){
data.push(getDataByConnection(connection));
@@ -430,7 +451,6 @@ define([
){
let SystemSignatures = require('app/ui/module/system_signature');
let connectionId = connection.getParameter('connectionId');
let sourceEndpoint = connection.endpoints[0];
let targetEndpoint = connection.endpoints[1];
let sourceSystem = $(sourceEndpoint.element);
@@ -1704,6 +1724,7 @@ define([
showSystemInfo: showSystemInfo,
showConnectionInfo: showConnectionInfo,
showFindRouteDialog: showFindRouteDialog,
getLabelByEndpoint: getLabelByEndpoint,
getConnectionsByType: getConnectionsByType,
getDataByConnection: getDataByConnection,
searchConnectionsBySystems: searchConnectionsBySystems,

View File

@@ -209,7 +209,7 @@ define([
Page.initTabChangeObserver();
// init hidden context menu elements
Page.initMapContextMenus();
Page.renderMapContextMenus();
// init map module
mapModule.initMapModule();
@@ -415,7 +415,7 @@ define([
// map update done, init new trigger
// get the current update delay (this can change if a user is inactive)
let mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
let mapUpdateDelay = Util.getCurrentTriggerDelay(logKeyServerMapData, 0);
// init new trigger
initMapUpdatePing(false);

View File

@@ -749,6 +749,11 @@ define([
.select2('destroy');
});
// global "close" trigger for context menus
documentElement.on('click', function(){
MapContextMenu.closeMenus();
});
// disable menu links based on current map config
documentElement.on('pf:updateMenuOptions', function(e, data){
let hasRightMapDelete = MapUtil.checkRight('map_delete', data.mapConfig);
@@ -1181,12 +1186,15 @@ define([
/**
* add "hidden" context menu elements to page
*/
let initMapContextMenus = () => {
$('#' + config.dynamicElementWrapperId).append(
MapContextMenu.initMapContextMenu(),
MapContextMenu.initConnectionContextMenu(),
MapContextMenu.initSystemContextMenu(Init.systemStatus)
);
let renderMapContextMenus = () => {
Promise.all([
MapContextMenu.renderMapContextMenu(),
MapContextMenu.renderConnectionContextMenu(),
MapContextMenu.renderEndpointContextMenu(),
MapContextMenu.renderSystemContextMenu(Init.systemStatus)
]).then(payloads => {
$('#' + config.dynamicElementWrapperId).append(payloads.join(''));
});
};
/**
@@ -1315,7 +1323,7 @@ define([
return {
initTabChangeObserver: initTabChangeObserver,
initMapContextMenus: initMapContextMenus
renderMapContextMenus: renderMapContextMenus
};
});

View File

@@ -2,59 +2,23 @@
* Render controller
*/
define(['jquery', 'mustache'], function($, Mustache){
define(['jquery', 'mustache'], ($, Mustache) => {
'use strict';
/**
* init function will be called before and after a new module is loaded
* @param functionName
* @param config
*/
let initModule = function(functionName, config){
if(
typeof config.functions === 'object' &&
typeof config.functions[functionName] === 'function'
){
config.functions[functionName](config);
}
};
/**
* load a template and render is with Mustache
* @param config
* render Mustache template
* @param path
* @param data
* @returns {Promise<any>}
*/
let showModule = function(config, data){
// require module template
requirejs(['text!templates/' + config.name + '.html'], function(template){
// check for an id, if module already exists, do not insert again
if(
data.id === 'undefined' ||
$('#' + data.id).length === 0
){
let content = Mustache.render(template, data);
// display module
switch(config.link){
case 'prepend':
config.position.prepend(content);
break;
case 'before':
config.position.before(content);
break;
case 'after':
config.position.after(content);
break;
default:
config.position.append(content);
}
}
// init module function after render
initModule('after', config);
});
let render = (path, data) => {
let renderExecutor = (resolve) => {
requirejs(['text!templates/' + path + '.html'], template => {
resolve(Mustache.render(template, data));
});
};
return new Promise(renderExecutor);
};
/**
@@ -180,7 +144,7 @@ define(['jquery', 'mustache'], function($, Mustache){
};
return {
showModule: showModule,
render: render,
highlightJson: highlightJson
};
});

View File

@@ -200,7 +200,7 @@ define([
let mapUrl = $(this).find('span').text().trim();
Util.copyToClipboard(mapUrl).then(payload => {
if(payload.data){
Util.showNotify({title: 'Copied to clipbaord', text: mapUrl, type: 'success'});
Util.showNotify({title: 'Copied to clipboard', text: mapUrl, type: 'success'});
}
});
});
@@ -1155,26 +1155,33 @@ define([
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// unset formatted string (to much content)
if(cellData.formatted){
// clone data before delete() values
cellData = Object.assign({}, cellData);
delete(cellData.formatted);
}
$(cell).on('mouseenter', function(e){
let cell = $(this);
if(!cell.data('bs.popover')){
if(cellData.formatted){
// clone data before delete() values
cellData = Object.assign({}, cellData);
delete(cellData.formatted);
}
let jsonHighlighted = Render.highlightJson(cellData);
let content = '<pre><code>' + jsonHighlighted + '</code></pre>';
let jsonHighlighted = Render.highlightJson(cellData);
let content = '<pre><code>' + jsonHighlighted + '</code></pre>';
// open popover with raw log data
$(cell).popover({
placement: 'left',
html: true,
trigger: 'hover',
content: content,
container: 'body',
title: 'Raw data',
delay: {
show: 180,
hide: 0
// open popover with raw log data
cell.popover({
placement: 'left',
html: true,
trigger: 'hover',
content: content,
container: 'body',
title: 'Raw data',
delay: {
show: 180,
hide: 0
}
});
cell.popover('show');
}
});
}

View File

@@ -232,6 +232,7 @@ define([
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
endpointsBubble: (rowData.hasOwnProperty('endpointsBubble')) ? rowData.endpointsBubble | 0 : 1,
connections: (rowData.hasOwnProperty('connections')) ? rowData.connections.value | 0 : 0,
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
};
@@ -324,7 +325,8 @@ define([
wormholesReduced: routeDialogData.hasOwnProperty('wormholesReduced') ? parseInt(routeDialogData.wormholesReduced) : 0,
wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt(routeDialogData.wormholesCritical) : 0,
wormholesFrigate: routeDialogData.hasOwnProperty('wormholesFrigate') ? parseInt(routeDialogData.wormholesFrigate) : 0,
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt(routeDialogData.wormholesEOL) : 0
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt(routeDialogData.wormholesEOL) : 0,
endpointsBubble: routeDialogData.hasOwnProperty('endpointsBubble') ? parseInt(routeDialogData.endpointsBubble) : 0
}]
};
@@ -731,7 +733,7 @@ define([
// button class for flag (e.g. "secure" routes)
let flagButtonClass = routeData.flag === 'secure' ? 'txt-color-success' : '';
let connectionButton = '<i class="fas ' + ['fa-link', 'txt-color'].join(' ') + '"></i>';
let connectionButton = '<i class="fas ' + ['fa-code-branch', 'fa-rotate-270', 'txt-color'].join(' ') + '"></i>';
let flagButton = '<i class="fas ' + ['fa-shield-alt', 'txt-color', flagButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fas ' + ['fa-sync'].join(' ') + '"></i>';
let searchButton = '<i class="fas ' + ['fa-search'].join(' ') + '"></i>';
@@ -760,6 +762,7 @@ define([
wormholesCritical: routeData.wormholesCritical,
wormholesFrigate: routeData.wormholesFrigate,
wormholesEOL: routeData.wormholesEOL,
endpointsBubble: routeData.endpointsBubble,
connections: {
value: 0,
button: connectionButton
@@ -994,7 +997,7 @@ define([
}
},{
targets: 5,
title: '<i title="toggle connections" data-toggle="tooltip" class="fas fa-link text-right"></i>',
title: '<i title="toggle connections" data-toggle="tooltip" class="fas fa-code-branch fa-rotate-270 text-right"></i>',
orderable: false,
searchable: false,
width: 10,

View File

@@ -2933,7 +2933,7 @@ define([
};
/**
* check an element for attached event by name
* check an element for attached jQuery event by name
* -> e.g. eventName = 'click.myNamespace'
* @param element
* @param eventName
@@ -2941,22 +2941,25 @@ define([
*/
let hasEvent = (element, eventName) => {
let exists = false;
let parts = eventName.split('.');
let name = parts[0];
let namespace = parts.length === 2 ? parts[1] : false;
let events = $._data( element[0], 'events')[name];
if(events){
if(namespace){
// seach events by namespace
for(let event of events){
if(event.namespace === namespace){
exists = true;
break;
let allEvents = $._data(element[0], 'events');
if(allEvents){
let parts = eventName.split('.');
let name = parts[0];
let events = allEvents[name];
if(events){
let namespace = parts.length === 2 ? parts[1] : false;
if(namespace){
// search events by namespace
for(let event of events){
if(event.namespace === namespace){
exists = true;
break;
}
}
}else{
// at least ONE event of the given name found
exists = true;
}
}else{
// at least ONE event of the given name found
exists = true;
}
}
return exists;

View File

@@ -10388,7 +10388,8 @@
// in IE the top left corner is what it placed at the desired location. This will not
// be fixed. IE8 is not going to be supported for much longer.
var ts = "translate(-50%, calc(-50% - .5px))";
//var ts = "translate(-50%, -50%)";
var ts = "translate3d(-8px, 5px, 0)";
div.style.webkitTransform = ts;
div.style.mozTransform = ts;
div.style.msTransform = ts;

View File

@@ -49,7 +49,7 @@
<div id="{{mapInfoSystemsId}}" class="pf-dynamic-area">
</div>
<h4><i class="fas fa-link fa-lg fa-fw"></i> Connections</h4>
<h4><i class="fas fa-code-branch fa-rotate-270 fa-lg fa-fw"></i> Connections</h4>
<div id="{{mapInfoConnectionsId}}" class="pf-dynamic-area"></div>
</div>

View File

@@ -3,7 +3,7 @@
<ul class="nav navbar-nav {{dialogNavigationClass}}">
<li class="{{dialogNavLiClass}} active"><a data-target="#pf-manual-map" href="#"><i class="fas fa-sitemap fa-fw"></i>&nbsp;Map</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-system" href="#"><i class="fas fa-sun fa-fw"></i>&nbsp;System</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-connection" href="#"><i class="fas fa-link fa-fw"></i>&nbsp;Connection</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-connection" href="#"><i class="fas fa-code-branch fa-rotate-270 fa-fw"></i>&nbsp;Connection</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-signature" href="#"><i class="fas fa-signature fa-fw"></i>&nbsp;Signature</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-share" href="#"><i class="fas fa-share-alt fa-fw"></i>&nbsp;Share</a></li>
<li class="{{dialogNavLiClass}}"><a data-target="#pf-manual-chart" href="#"><i class="fas fa-chart-bar fa-fw"></i>&nbsp;Chart</a></li>
@@ -16,41 +16,53 @@
<div id="{{scrollspyId}}">
<h2 id="pf-manual-map"><i class="fas fa-sitemap fa-fw"></i>&nbsp;&nbsp;Map</h2>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4>Map types</h4>
<p>
<em class="pf-brand">pathfinder</em>&nbsp;&nbsp;supports 3 different types of maps. Systems <small>(<i class="fas fa-sun fa-fw"></i><a href="#" data-target="#pf-manual-system">more</a>)</small>
and connections <small>(<i class="fas fa-code-branch fa-rotate-270 fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small> can be added to them. Maps are also referred to as <em>"Chain Map"</em> or <em>"Chain"</em>:
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-private"></i>private map<small> (is not visible for other pilots, unless you invite them)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-corporation"></i>corporation map<small> (can be used by any corporation member)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-alliance"></i>alliance map<small> (can be used by any alliance member)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-global"></i>global map<small> (this maps are static and can´t be created by users)</small></li>
</ul>
<p>
Up to 5 different maps can be used simultaneously. <span class="txt-color txt-color-blue">Alliance maps</span> require appropriate rules to be created.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-map-scope">Map scope</h4>
<p>
Each map has a <em>"scope"</em> that affects how systems will be added automatically to it:
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>wormholes -<small> (w-space systems and chain exit systems are tracked)</small></li>
<li>stargates -<small> (k-space systems and direct neighboured systems are tracked)</small></li>
<li>all -<small> (any system will be tracked)</small></li>
<li>none -<small> (system tracking is disabled)</small></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-location-arrow fa-fw"></i> Map tracking</h4>
<p>
If "map tracking" is <span class="txt-color txt-color-greenLight">on</span>, new systems <small>(<i class="fas fa-sun fa-fw"></i><a href="#" data-target="#pf-manual-system">more</a>)</small>
and connections <small>(<i class="fas fa-code-branch fa-rotate-270 fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small>
will be automatically added to the current map <small>(<i class="fas fa-sitemap fa-fw"></i><a href="#" data-target="#pf-manual-map">more</a>)</small>.
This can only work if your current position is known by <em class="pf-brand">pathfinder</em>.<br>
The map scope <small>(<i class="fas fa-crosshairs fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-map-scope">more</a>)</small> defines which systems are affected.<br>
The connection scope <small>(<i class="fas fa-crosshairs fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a>)</small> will be auto-detected (e.g. wormhole connection).
This is achieved by calculating the jump distance between your current system and system you came from.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4>Map types</h4>
<p>
<em class="pf-brand">pathfinder</em>&nbsp;&nbsp;supports 3 different types of maps. Systems <small>(<i class="fas fa-sun fa-fw"></i><a href="#" data-target="#pf-manual-system">more</a>)</small>
and connections <small>(<i class="fas fa-link fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small> can be added to them. Maps are also referred to as <em>"Chain Map"</em> or <em>"Chain"</em>:
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-private"></i>private map<small> (is not visible for other pilots, unless you invite them)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-corporation"></i>corporation map<small> (can be used by any corporation member)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-alliance"></i>alliance map<small> (can be used by any alliance member)</small></li>
<li><i class="fa-li fas fa-circle fa-fw pf-map-type-global"></i>global map<small> (this maps are static and can´t be created by users)</small></li>
</ul>
<p>
Up to 5 different maps can be used simultaneously. <span class="txt-color txt-color-blue">Alliance maps</span> require appropriate rules to be created.
</p>
<h4 id="pf-manual-scrollspy-anchor-map-scope">Map scope</h4>
<p>
Each map has a <em>"scope"</em> that affects how systems will be added automatically to it:
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>wormholes -<small> (w-space systems and chain exit systems are tracked)</small></li>
<li>stargates -<small> (k-space systems and direct neighboured systems are tracked)</small></li>
<li>all -<small> (any system will be tracked)</small></li>
<li>none -<small> (system tracking is disabled)</small></li>
</ul>
<h4><i class="fas fa-location-arrow fa-fw"></i> Map tracking</h4>
<p>
If "map tracking" is <span class="txt-color txt-color-greenLight">on</span>, new systems <small>(<i class="fas fa-sun fa-fw"></i><a href="#" data-target="#pf-manual-system">more</a>)</small>
and connections <small>(<i class="fas fa-link fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small>
will be automatically added to the current map <small>(<i class="fas fa-sitemap fa-fw"></i><a href="#" data-target="#pf-manual-map">more</a>)</small>.
This can only work if your current position is known by <em class="pf-brand">pathfinder</em>.<br>
The map scope <small>(<i class="fas fa-crosshairs fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-map-scope">more</a>)</small> defines which systems are affected.<br>
The connection scope <small>(<i class="fas fa-crosshairs fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a>)</small> will be auto-detected (e.g. wormhole connection).
This is achieved by calculating the jump distance between your current system and system you came from.
</p>
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-map-contextmenu">Context menu</h4>
<p>
<kbd>right click</kbd> somewhere on the map to open the context menu.
@@ -62,46 +74,64 @@
<li><i class="fas fa-sitemap fa-fw"></i> Map related options (edit map, information)</li>
<li><i class="fas fa-trash fa-fw"></i> Delete selected systems <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-map-select"><i class="fas fa-object-ungroup fa-fw"></i> Select methods</h4>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>Frame Select:<small> Multiple systems can be selected by </small><kbd>click</kbd> + <kbd>drag</kbd></li>
<li>Click Select:<small> Individual systems can be selected by holding </small><kbd>ctrl</kbd> + <kbd>click</kbd> <small> at a system</small></li>
</ul>
<p>
Locked systems <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can´t be selected.
</p>
<h4><i class="fas fa-magnet fa-th"></i> Grid snapping</h4>
<p>
The <em>"Grid snapping"</em> option can be activated on the "Map Menu" <small>(<i class="fas fa-sitemap fa-fw"></i>)</small>. Systems will snap to a <samp>20x20px</samp> grid.
A grid overlay appears on the map.
</p>
<h4><i class="fas fa-magnet fa-fw"></i> Magnetizing</h4>
<p>
The <em>"Magnetizing"</em> option can be activated on the "Map Menu" <small>(<i class="fas fa-sitemap fa-fw"></i>)</small>.
If active, systems effect each other while <kbd>move</kbd>/<kbd>drag&amp;drop</kbd> and will rearrange themselves automatically on the map. This prevents system "overlapping"
</p>
<h4><i class="fas fa-link fa-fw"></i> Signatures</h4>
<p>
The <em>"Signatures"</em> option adds additional overlays to all connection endpoints.
If a Connection <small>(<i class="fas fa-link fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small>
has a Signature <small>(<i class="fas fa-signature fa-fw"></i><a href="#" data-target="#pf-manual-signature">more</a>)</small>
mapped to it, in either the source or target system, <em class="pf-brand">pathfinder</em> displays that information on map
</p>
<h4><i class="fas fa-compress fa-fw"></i> Compact</h4>
<p>
The <em>"Compact"</em> option triggers a "compressed" map layout. Active Pilots are shown "inline" next to the name of a system.
</p>
<h4><i class="fas fa-history fa-fw"></i> Update counter</h4>
<div class="pf-map-overlay" style="position: initial; display: block; padding-top: 1px; float: left; margin: 0 10px 10px 0;">
<div class="{{pieChartClass}} {{mapCounterClass}}" data-percent="40">
<span style="position: absolute; line-height: 30px; margin-left: 10px;">4</span>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-map-select"><i class="fas fa-object-ungroup fa-fw"></i> Select methods</h4>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>Frame Select:<small> Multiple systems can be selected by </small><kbd>click</kbd> + <kbd>drag</kbd></li>
<li>Click Select:<small> Individual systems can be selected by holding </small><kbd>ctrl</kbd> + <kbd>click</kbd> <small> at a system</small></li>
</ul>
<p>
Locked systems <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can´t be selected.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-magnet fa-th"></i> Grid snapping</h4>
<p>
The <em>"Grid snapping"</em> option can be activated on the "Map Menu" <small>(<i class="fas fa-sitemap fa-fw"></i>)</small>. Systems will snap to a <samp>20x20px</samp> grid.
A grid overlay appears on the map.
</p>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-magnet fa-fw"></i> Magnetizing</h4>
<p>
The <em>"Magnetizing"</em> option can be activated on the "Map Menu" <small>(<i class="fas fa-sitemap fa-fw"></i>)</small>.
If active, systems effect each other while <kbd>move</kbd>/<kbd>drag&amp;drop</kbd> and will rearrange themselves automatically on the map. This prevents system "overlapping"
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-link fa-fw"></i> Signatures</h4>
<p>
The <em>"Signatures"</em> option adds additional overlays to all connection endpoints.
If a Connection <small>(<i class="fas fa-code-branch fa-rotate-270 fa-fw"></i><a href="#" data-target="#pf-manual-connection">more</a>)</small>
has a Signature <small>(<i class="fas fa-signature fa-fw"></i><a href="#" data-target="#pf-manual-signature">more</a>)</small>
mapped to it, in either the source or target system, <em class="pf-brand">pathfinder</em> displays that information on map
</p>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-compress fa-fw"></i> Compact</h4>
<p>
The <em>"Compact"</em> option triggers a "compressed" map layout. Active Pilots are shown "inline" next to the name of a system.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-history fa-fw"></i> Update counter</h4>
<div class="pf-map-overlay" style="position: initial; display: block; padding-top: 1px; float: left; margin: 0 10px 10px 0;">
<div class="{{pieChartClass}} {{mapCounterClass}}" data-percent="40">
<span style="position: absolute; line-height: 30px; margin-left: 10px;">4</span>
</div>
</div>
<p>
The <em>"Update counter"</em> starts counting backwards during map interaction. While the counter is active, no data is pushed to server.
Once the counter hits 0, all map date will be stored and active pilots will receive the map updates.<br>
There is no need for any safe/edit buttons.
</p>
</div>
</div>
<p>
The <em>"Update counter"</em> starts counting backwards during map interaction. While the counter is active, no data is pushed to server.
Once the counter hits 0, all map date will be stored and active pilots will receive the map updates.<br>
There is no need for any safe/edit buttons.
</p>
<div class="clearfix"></div>
<hr class="pf-manual-scroll-break">
@@ -114,17 +144,24 @@
Pilots can interact with systems like "delete systems" <small>(<i class="fas fa-trash fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small> or
"move systems" <small>(<i class="fas fa-hand-paper fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-move">more</a>)</small>.
</p>
<h4 id="pf-manual-scrollspy-anchor-system-active">Active system</h4>
<p>
Any system on a map can be set as "active" by <kbd>click</kbd>. <br>
Just one system per map can have an active state.
The active system has a <span style="-webkit-box-shadow: #ffffbb 0px 0px 8px 0px;box-shadow: #ffffbb 0px 0px 8px 0px; display: inline-block; margin: 0 5px; padding: 0 3px;">light yellow</span> shadow.
Additional system information is shown below the map.
</p>
<h4>Name / Alias</h4>
<p>
Systems can be renamed with an alias by <kbd>double-click</kbd> the name. System aliases are stored server side and are visible to any pilot on the map.
</p>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-active">Active system</h4>
<p>
Any system on a map can be set as "active" by <kbd>click</kbd>. <br>
Just one system per map can have an active state.
The active system has a <span style="-webkit-box-shadow: #ffffbb 0px 0px 8px 0px;box-shadow: #ffffbb 0px 0px 8px 0px; display: inline-block; margin: 0 5px; padding: 0 3px;">light yellow</span> shadow.
Additional system information is shown below the map.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4>Name / Alias</h4>
<p>
Systems can be renamed with an alias by <kbd>double-click</kbd> the name. System aliases are stored server side and are visible to any pilot on the map.
</p>
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-system-security">Security status</h4>
<p>
Any <em>"K-space"</em> system in <em>"New Eden"</em> has a fixed <em>"Security status"</em> between <samp>-1.0</samp> and <samp>+1.0</samp>.
@@ -223,45 +260,58 @@
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-system-status">System status</h4>
<p>
The border color indicates the current status of a system.<br>
The status can be changed by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-contextmenu">more</a>)</small>.
</p>
<ul class="fa-ul">
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-unknown"></i> no status set <small>(unknown)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-friendly"></i> friendly <small>(in the possession of your corp/ally or allied entities)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-occupied"></i> occupied <small>(hostiles structures found but not active)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-hostile"></i> hostile <small>(hostile activity noticed recently)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-empty"></i> empty <small>(system is not occupied or active)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-unscanned"></i> unscanned <small>(system has unscanned signatures)</small></li>
</ul>
<h4>System effect</h4>
<p>
Effects of wormhole systems are shown by a <i class="fas fa-square fa-fw"></i> at the top right of a system.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-square fa-fw pf-system-effect"></i> No effect</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-magnetar"></i> Magnetar</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-redgiant"></i> Red Giant</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-pulsar"></i> Pulsar</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-wolfrayet"></i> Wolf-Rayet</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-cataclysmic"></i> Cataclysmic Variable</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-blackhole"></i> Blackhole</li>
</ul>
<h4>Active pilots</h4>
<p>
If a system has active pilots, a tooltip is shown with the current number of pilots. <br>
Systems with active pilots are bigger than empty systems and provide morermation than others.<br>
During <kbd>mouseover</kbd> the <small>(<i class="fas fa-angle-down fa-fw"></i>)</small> icon more detailed information is shown.
</p>
<h4 id="pf-manual-scrollspy-anchor-system-move"><i class="fas fa-hand-paper fa-fw"></i> Move</h4>
<p>
Any system that is not <em>"Locked"</em> <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can be moved,
by <kbd>click</kbd> + <kbd>drag</kbd> the systems security label (top right).<br>
In order to move multiple systems at once, make sure all of them are selected <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-select">more</a>)</small>.
Now <kbd>drag</kbd> one selected systems and all others follow.
</p>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-status">System status</h4>
<p>
The border color indicates the current status of a system.<br>
The status can be changed by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-contextmenu">more</a>)</small>.
</p>
<ul class="fa-ul">
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-unknown"></i> no status set <small>(unknown)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-friendly"></i> friendly <small>(in the possession of your corp/ally or allied entities)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-occupied"></i> occupied <small>(hostiles structures found but not active)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-hostile"></i> hostile <small>(hostile activity noticed recently)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-empty"></i> empty <small>(system is not occupied or active)</small></li>
<li><i class="fa-li far fa-square fa-lg fa-fw pf-system-status-unscanned"></i> unscanned <small>(system has unscanned signatures)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
<h4>System effect</h4>
<p>
Effects of wormhole systems are shown by a <i class="fas fa-square fa-fw"></i> at the top right of a system.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-square fa-fw pf-system-effect"></i> No effect</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-magnetar"></i> Magnetar</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-redgiant"></i> Red Giant</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-pulsar"></i> Pulsar</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-wolfrayet"></i> Wolf-Rayet</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-cataclysmic"></i> Cataclysmic Variable</li>
<li><i class="fa-li fas fa-square fa-fw pf-system-effect-blackhole"></i> Blackhole</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4>Active pilots</h4>
<p>
If a system has active pilots, a tooltip is shown with the current number of pilots. <br>
Systems with active pilots are bigger than empty systems and provide morermation than others.<br>
During <kbd>mouseover</kbd> the <small>(<i class="fas fa-angle-down fa-fw"></i>)</small> icon more detailed information is shown.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-move"><i class="fas fa-hand-paper fa-fw"></i> Move</h4>
<p>
Any system that is not <em>"Locked"</em> <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can be moved,
by <kbd>click</kbd> + <kbd>drag</kbd> the systems security label (top right).<br>
In order to move multiple systems at once, make sure all of them are selected <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-select">more</a>)</small>.
Now <kbd>drag</kbd> one selected systems and all others follow.
</p>
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-system-contextmenu">Context menu</h4>
<p>
<kbd>right click</kbd> a system on the map to open the context menu.
@@ -274,42 +324,54 @@
<li><i class="fas fa-reply fa-rotate-180 fa-fw"></i> Waypoint options for this system <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-waypoint">more</a></small></li>
<li><i class="fas fa-trash fa-fw"></i> Delete this system and all connections <small><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a></small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-system-locked"><i class="fas fa-lock fa-fw"></i> Locked system</h4>
<p>
Locked systems can´t be selected <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-select">more</a>)</small>,
moved <small>(<i class="fas fa-hand-paper fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-move">more</a>)</small>
or deleted <small>(<i class="fas fa-trash fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small>.
</p>
<h4 id="pf-manual-scrollspy-anchor-system-rally"><i class="fas fa-volume-up fa-fw"></i> Rally point</h4>
<p>
Systems can be marked as <span class="pf-system-info-rally"><span class="pf-system-head" style="padding: 0 5px;">Rally point</span></span>.
When a new "<em>Rally point</em>" is set, you can optional enter a message and set various "<em>Poke</em>" options, in order to send notifications to other active pilots.<br>
<em>Slack</em> and Email pokes require a valid map configuration (map settings dialog) before they can be used.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><i class="fas fa-volume-up fa-fw"></i> Desktop poke -<small> (send OS browser popup messages)</small></li>
<li><i class="fab fa-slack-hash fa-fw"></i> Slack poke -<small> (send poke message to a <em>Slack</em> channel)</small></li>
<li><i class="fab fa-discord fa-fw"></i> Discord poke -<small> (send poke message to a <em>Discord</em> channel)</small></li>
<li><i class="fas fa-envelope fa-fw"></i> Email poke -<small> (send a mail with your poke message)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-system-waypoint"><i class="fas fa-flag-checkered fa-fw"></i> Waypoints</h4>
<p>
Waypoints can be set to systems. Waypoint options are identical to their in game options.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>set destination -<small> (clear other waypoints and set new destination)</small></li>
<li>add new [start] -<small> (add new waypoint in front of your waypoint queue)</small></li>
<li>add new [end] -<small> (add new waypoint to the end of your waypoint queue)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-system-delete"><i class="fas fa-trash fa-fw"></i> Delete system</h4>
<p>
Any system that is not "Locked" <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can be deleted from a map.
</p>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-rally"><i class="fas fa-volume-up fa-fw"></i> Rally point</h4>
<p>
Systems can be marked as <span class="pf-system-info-rally"><span class="pf-system-head" style="padding: 0 5px;">Rally point</span></span>.
When a new "<em>Rally point</em>" is set, you can optional enter a message and set various "<em>Poke</em>" options, in order to send notifications to other active pilots.<br>
<em>Slack</em> and Email pokes require a valid map configuration (map settings dialog) before they can be used.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><i class="fas fa-volume-up fa-fw"></i> Desktop poke -<small> (send OS browser popup messages)</small></li>
<li><i class="fab fa-slack-hash fa-fw"></i> Slack poke -<small> (send poke message to a <em>Slack</em> channel)</small></li>
<li><i class="fab fa-discord fa-fw"></i> Discord poke -<small> (send poke message to a <em>Discord</em> channel)</small></li>
<li><i class="fas fa-envelope fa-fw"></i> Email poke -<small> (send a mail with your poke message)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-waypoint"><i class="fas fa-flag-checkered fa-fw"></i> Waypoints</h4>
<p>
Waypoints can be set to systems. Waypoint options are identical to their in game options.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>set destination -<small> (clear other waypoints and set new destination)</small></li>
<li>add new [start] -<small> (add new waypoint in front of your waypoint queue)</small></li>
<li>add new [end] -<small> (add new waypoint to the end of your waypoint queue)</small></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-locked"><i class="fas fa-lock fa-fw"></i> Locked system</h4>
<p>
Locked systems can´t be selected <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-select">more</a>)</small>,
moved <small>(<i class="fas fa-hand-paper fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-move">more</a>)</small>
or deleted <small>(<i class="fas fa-trash fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-delete">more</a>)</small>.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-system-delete"><i class="fas fa-trash fa-fw"></i> Delete system</h4>
<p>
Any system that is not "Locked" <small>(<i class="fas fa-lock fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-system-locked">more</a>)</small> can be deleted from a map.
</p>
</div>
</div>
<hr class="pf-manual-scroll-break">
{{! ================================================================================================================================================ }}
<h2 id="pf-manual-connection"><i class="fas fa-link fa-fw"></i>&nbsp;&nbsp;Connection (Stargate / Wormhole)</h2>
<h2 id="pf-manual-connection"><i class="fas fa-code-branch fa-rotate-270 fa-fw"></i>&nbsp;&nbsp;Connection (Stargate / Wormhole)</h2>
<p>
Connections between systems are represented by solid lines. Any connection requires two systems that are connected together.
</p>
@@ -322,42 +384,54 @@
<li>Switch Connection: <kbd>click</kbd><small> a <em>"Connection Endpoints"</em> and </small><kbd>drag</kbd><small> it to any other system</small></li>
<li>Add new System: <small>Add a system by using the context menu of a system (<a href="#" data-target="#pf-manual-scrollspy-anchor-system-contextmenu">more</a>)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-connection-scope"><i class="fas fa-crosshairs fa-fw"></i> Connection scope</h4>
<p>
Each connection has its own <em>"Scope"</em>. Scopes represent connection types that exist in game.<br>
Maps can be filtered by specific scopes <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-contextmenu">more</a>)</small>.<br>
The <em>"Scope"</em> of a connection can be changed by using the context menu of a connection <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><div class="pf-fake-connection"></div>&nbsp;&nbsp;Wormhole<small> (Wormhole has not yet had its stability significantly disrupted)</small></li>
<li><div class="pf-fake-connection pf-map-connection-stargate"></div>&nbsp;&nbsp;Stargate<small> (Stargates are static <em>"K-space"</em> connections)</small></li>
<li><div class="pf-fake-connection pf-map-connection-jumpbridge"></div>&nbsp;&nbsp;Jumpbridge<small> (Jumpbridges are player build <em>"K-space"</em> connections)</small></li>
<li><div class="pf-fake-connection pf-map-connection-abyssal"></div>&nbsp;&nbsp;Abyssal<small> (abyssal zone entrance <em>"a-space"</em> connections)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-connection-status">Connection status</h4>
<p>
Wormholes will gain various statuses during its <em>"Lifetime"</em>.<br>
In addition to this, connections can get custom statuses.<br>
The status can be changed by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><div class="pf-fake-connection pf-map-connection-wh-eol"></div> end of life<small> (Wormhole is the end of its natural lifetime)</small></li>
<li><div class="pf-fake-connection pf-map-connection-wh-reduced"></div> reduced<small> (Wormhole had its stability reduced, but not to a critical degree) &lt;50% mass left</small></li>
<li><div class="pf-fake-connection pf-map-connection-wh-critical"></div> critical<small> (Wormhole is on the verge of collapse) &lt;10% mass left</small></li>
<li><div class="pf-fake-connection pf-map-connection-frig"></div> Frigate hole<small> (Only the smallest ships pass through)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-connection-label"><i class="fas fa-tag fa-fw"></i> Connection label</h4>
<p>
In addition to its <em>"Lifetime Status" </em><small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a>)</small>, connections can be labeled with custom labels
to supply further information.<br>
Labels can be set by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><span class="label label-warning" style="color: #1d1d1d">frig</span> Frigate hole<small> (Only the smallest ships pass through)</small></li>
<li style="margin-top: 3px;"><span class="label label-danger"><i class="fas fa-exclamation-triangle"></i> save mass</span> save mass<small> (Wormhole mass has to be saved)</small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-connection-contextmenu">Context menu</h4>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-scope"><i class="fas fa-crosshairs fa-fw"></i> Connection scope</h4>
<p>
Each connection has its own <em>"Scope"</em>. Scopes represent connection types that exist in game.<br>
Maps can be filtered by specific scopes <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-map-contextmenu">more</a>)</small>.<br>
The <em>"Scope"</em> of a connection can be changed by using the context menu of a connection <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><div class="pf-fake-connection"></div>&nbsp;&nbsp;Wormhole<small> (Wormhole has not yet had its stability significantly disrupted)</small></li>
<li><div class="pf-fake-connection pf-map-connection-stargate"></div>&nbsp;&nbsp;Stargate<small> (Stargates are static <em>"K-space"</em> connections)</small></li>
<li><div class="pf-fake-connection pf-map-connection-jumpbridge"></div>&nbsp;&nbsp;Jumpbridge<small> (Jumpbridges are player build <em>"K-space"</em> connections)</small></li>
<li><div class="pf-fake-connection pf-map-connection-abyssal"></div>&nbsp;&nbsp;Abyssal<small> (abyssal zone entrance <em>"a-space"</em> connections)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-status">Connection status</h4>
<p>
Wormholes will gain various statuses during its <em>"Lifetime"</em>.<br>
In addition to this, connections can get custom statuses.<br>
The status can be changed by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><div class="pf-fake-connection pf-map-connection-wh-eol"></div> end of life<small> (Wormhole is the end of its natural lifetime)</small></li>
<li><div class="pf-fake-connection pf-map-connection-wh-reduced"></div> reduced<small> (Wormhole had its stability reduced, but not to a critical degree) &lt;50% mass left</small></li>
<li><div class="pf-fake-connection pf-map-connection-wh-critical"></div> critical<small> (Wormhole is on the verge of collapse) &lt;10% mass left</small></li>
<li><div class="pf-fake-connection pf-map-connection-frig"></div> Frigate hole<small> (Only the smallest ships pass through)</small></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-label"><i class="fas fa-tag fa-fw"></i> Connection label</h4>
<p>
In addition to its <em>"Lifetime Status" </em><small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a>)</small>, connections can be labeled with custom labels
to supply further information.<br>
Labels can be set by using the context menu <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small>.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li><span class="label label-warning" style="color: #1d1d1d">frig</span> Frigate hole<small> (Only the smallest ships pass through)</small></li>
<li style="margin-top: 3px;"><span class="label label-danger"><i class="fas fa-exclamation-triangle"></i> save mass</span> save mass<small> (Wormhole mass has to be saved)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-connection-contextmenu">Context menu (connection)</h4>
<p>
<kbd>right click</kbd> a connection on the map to open the context menu.
</p>
@@ -368,28 +442,62 @@
<li><i class="fas fa-reply fa-rotate-180 fa-fw"></i> Changes the status of this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a></small></li>
<li><i class="fas fa-trash fa-fw"></i> Delete this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-delete">more</a></small></li>
</ul>
<h4 id="pf-manual-scrollspy-anchor-connection-frig"><i class="fas fa-plane fa-fw"></i> Frigate hole</h4>
<p>
Wormholes can be labeled <small>(<i class="fas fa-tag fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-label">more</a>)</small> as <em>"Frigate hole"</em>.
Only frigate-sized Spaceships can pass through a <em>"Frigate hole"</em> <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a>)</small>.
</p>
<h4 id="pf-manual-scrollspy-anchor-connection-mass"><i class="fas fa-exclamation-triangle fa-fw"></i> Preserve mass</h4>
<p>
Wormholes can be labeled <small>(<i class="fas fa-tag fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-label">more</a>)</small> as <em>"Preserve mass"</em>.
Let your mates know about critical connections that should be mass-saved
(e.g. <span class="pf-system-sec-highSec">H</span> security exits) <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-security">more</a>)</small>.
</p>
<h4 id="pf-manual-scrollspy-anchor-connection-delete"><i class="fas fa-trash fa-fw"></i> Delete connection</h4>
<p>
Connections can be detached by several ways.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>Drag Connection: <small> <em>"Connection Endpoints"</em> can be </small><kbd>click</kbd> + <kbd>drag</kbd><small> away from its current system</small></li>
<li>Delete Connection: <small>Delete a connection by using the context menu of a connection (<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small></li>
<li>Delete System: <small>Delete a system by using the context menu of a connection (<a href="#" data-target="#pf-manual-scrollspy-anchor-system-contextmenu">more</a>)</small></li>
<li>Delete Systems: <small>Delete multiple systems by using the context menu of a map (<a href="#" data-target="#pf-manual-scrollspy-anchor-map-contextmenu">more</a>)</small></li>
</ul>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-frig"><i class="fas fa-plane fa-fw"></i> Frigate hole</h4>
<p>
Wormholes can be labeled <small>(<i class="fas fa-tag fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-label">more</a>)</small> as <em>"Frigate hole"</em>.
Only frigate-sized Spaceships can pass through a <em>"Frigate hole"</em> <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a>)</small>.
</p>
</div>
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-mass"><i class="fas fa-exclamation-triangle fa-fw"></i> Preserve mass</h4>
<p>
Wormholes can be labeled <small>(<i class="fas fa-tag fa-fw"></i><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-label">more</a>)</small> as <em>"Preserve mass"</em>.
Let your mates know about critical connections that should be mass-saved
(e.g. <span class="pf-system-sec-highSec">H</span> security exits) <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-security">more</a>)</small>.
</p>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-connection-delete"><i class="fas fa-trash fa-fw"></i> Delete connection</h4>
<p>
Connections can be detached by several ways.
</p>
<ul class="list-unstyled" style=" margin-left: 10px;">
<li>Drag Connection: <small> <em>"Connection Endpoints"</em> can be </small><kbd>click</kbd> + <kbd>drag</kbd><small> away from its current system</small></li>
<li>Delete Connection: <small>Delete a connection by using the context menu of a connection (<a href="#" data-target="#pf-manual-scrollspy-anchor-connection-contextmenu">more</a>)</small></li>
<li>Delete System: <small>Delete a system by using the context menu of a connection (<a href="#" data-target="#pf-manual-scrollspy-anchor-system-contextmenu">more</a>)</small></li>
<li>Delete Systems: <small>Delete multiple systems by using the context menu of a map (<a href="#" data-target="#pf-manual-scrollspy-anchor-map-contextmenu">more</a>)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
</div>
</div>
<h4 id="pf-manual-endpoint">Endpoints</h4>
<p>
The two endpoints of a connection support <kbd>drag&amp;drop</kbd> for either twitch the connection to a a new target system or use the context menu for endpoint specific actions.
</p>
<h4 id="pf-manual-scrollspy-anchor-endpoint-contextmenu">Context menu (endpoint)</h4>
<p>
<kbd>right click</kbd> a connection endpoint on the map to open the context menu.
</p>
<ul class="list-unstyled well" style=" margin-left: 10px;">
<li><i class="fas fa-globe fa-fw"></i> Toggles this endpoint <em>"bubbled"</em> <small><a href="#" data-target="#pf-manual-scrollspy-anchor-endpoint-bubble">more</a></small></li>
</ul>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4 id="pf-manual-scrollspy-anchor-endpoint-bubble"><i class="fas fa-globe fa-fw"></i> Bubbled (endpoint)</h4>
<p>
A connection endpoint (e.g. wormhole, stargate,..) can be flagged as <em>"bubbled"</em>. Bubbled endpoints have a&nbsp;&nbsp;<span class="pf-endpoint-bubble"></span>&nbsp;&nbsp;mark around them on map.
</p>
</div>
<div class="col-xs-12 col-md-6">
</div>
</div>
<hr class="pf-manual-scroll-break">
{{! ================================================================================================================================================ }}
@@ -398,42 +506,55 @@
The <em>"Signature table"</em> of a system is shown below the map. Any active system <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small> has its own <em>"Signature table"</em>.
Signatures found in a system can be added to the table in order to share information. The table represents a record of the current scan process of a system.
</p>
<h4><i class="fas fa-tasks fa-fw"></i> Progress bar</h4>
<p>
The scan <em>"Progress bar"</em> is a visual indicator for the scan progress of a system. You can see how many signatures are scanned already and what is left.
Anytime a new signature is added to the <em>"Signature table"</em> the <em>"Progress bar"</em> will be updated automatically. The bar color indicates the progress.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-circle txt-color txt-color-danger"></i></span> not scanned <small>(System scanned to &lt;30%)</small></li>
<li><i class="fa-li fas fa-circle txt-color txt-color-warning"></i></span> bad scanned <small>(System scanned to &lt;100%)</small></li>
<li><i class="fa-li fas fa-circle txt-color txt-color-success"></i></span> full scanned <small>(System scanned to 100%)</small></li>
</ul>
<h4><i class="fas fa-paste fa-fw"></i> Signature reader</h4>
<p>
The <em>"Signature reader"</em> functionality allows pilots to add and update multiple signatures at once.
In order to copy signatures from <em>"EVE"</em> to <em class="pf-brand">pathfinder</em>, do the following steps.
</p>
<ol>
<li><kbd>ctrl</kbd> + <kbd>a</kbd> <small>(select all/some signatures in the scanning window)</small></li>
<li style="margin-top: 3px;"><kbd>ctrl</kbd> + <kbd>c</kbd> <small>(copy selected signatures to clipboard)</small></li>
<li style="margin-top: 3px;"><kbd>click</kbd> the <em>"Signature reader"</em> button <small>(open the <em>"Signature reader"</em> dialog)</small></li>
<li style="margin-top: 3px;"><kbd>ctrl</kbd> + <kbd>v</kbd> on the input field <small>(paste copied signatures into dialog)</small></li>
</ol>
<p>
Advanced pilots can skip number 3.!<br>
Make sure, you have the right system marked as active <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small>.<br>
<kbd>click</kbd> the browser tab were <em class="pf-brand">pathfinder</em> is open. Then press <kbd>ctrl</kbd> + <kbd>v</kbd>.<br>
<em class="pf-brand">pathfinder</em> automatically detect the data format and updates the <em>"Signature table"</em>.
</p>
<h4><i class="fas fa-trash fa-fw"></i> Delete signatures</h4>
<p>
Signatures can be detached by several ways.
</p>
<ul>
<li>Clear Signatures: <small>Delete all signatures by </small><kbd>click</kbd><small> at the <em>"Clear Signatures"</em> button</small></li>
<li>Delete Signature: <small>Delete a signature by </small><kbd>click</kbd><small> at the (<i class="fas fa-times fa-fw"></i>) button at the end of a row</small></li>
<li>Automatically: <small>Signatures will be deleted automatically after some days</small></li>
</ul>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-tasks fa-fw"></i> Progress bar</h4>
<p>
The scan <em>"Progress bar"</em> is a visual indicator for the scan progress of a system. You can see how many signatures are scanned already and what is left.
Anytime a new signature is added to the <em>"Signature table"</em> the <em>"Progress bar"</em> will be updated automatically. The bar color indicates the progress.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-circle txt-color txt-color-danger"></i></span> not scanned <small>(System scanned to &lt;30%)</small></li>
<li><i class="fa-li fas fa-circle txt-color txt-color-warning"></i></span> bad scanned <small>(System scanned to &lt;100%)</small></li>
<li><i class="fa-li fas fa-circle txt-color txt-color-success"></i></span> full scanned <small>(System scanned to 100%)</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-paste fa-fw"></i> Signature reader</h4>
<p>
The <em>"Signature reader"</em> functionality allows pilots to add and update multiple signatures at once.
In order to copy signatures from <em>"EVE"</em> to <em class="pf-brand">pathfinder</em>, do the following steps.
</p>
<ol>
<li><kbd>ctrl</kbd> + <kbd>a</kbd> <small>(select all/some signatures in the scanning window)</small></li>
<li style="margin-top: 3px;"><kbd>ctrl</kbd> + <kbd>c</kbd> <small>(copy selected signatures to clipboard)</small></li>
<li style="margin-top: 3px;"><kbd>click</kbd> the <em>"Signature reader"</em> button <small>(open the <em>"Signature reader"</em> dialog)</small></li>
<li style="margin-top: 3px;"><kbd>ctrl</kbd> + <kbd>v</kbd> on the input field <small>(paste copied signatures into dialog)</small></li>
</ol>
<p>
Advanced pilots can skip number 3.!<br>
Make sure, you have the right system marked as active <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small>.<br>
<kbd>click</kbd> the browser tab were <em class="pf-brand">pathfinder</em> is open. Then press <kbd>ctrl</kbd> + <kbd>v</kbd>.<br>
<em class="pf-brand">pathfinder</em> automatically detect the data format and updates the <em>"Signature table"</em>.
</p>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-trash fa-fw"></i> Delete signatures</h4>
<p>
Signatures can be detached by several ways.
</p>
<ul>
<li>Clear Signatures: <small>Delete all signatures by </small><kbd>click</kbd><small> at the <em>"Clear Signatures"</em> button</small></li>
<li>Delete Signature: <small>Delete a signature by </small><kbd>click</kbd><small> at the (<i class="fas fa-times fa-fw"></i>) button at the end of a row</small></li>
<li>Automatically: <small>Signatures will be deleted automatically after some days</small></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
</div>
</div>
<hr class="pf-manual-scroll-break">
{{! ================================================================================================================================================ }}
@@ -471,29 +592,35 @@
<em class="pf-brand">pathfinder</em> comes along with several visual charts graphs.
In order to provide the pilot with useful information about his environment, data visualisation is a good way to compress the amount of relevant data.
</p>
<h4><i class="fas fa-align-left fa-fw"></i> Trade hub range</h4><p>
<p>
The <em>"Trade hub range"</em> table is available for any <em>"K-space"</em> system. Each row represents the jump distance to a main <em>"Trade-Hub"</em>.
Each system jump is represented by a <i class="fas fa-square fa-fw"></i> with the color of its <em>"Security status"</em> <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-security">more</a>)</small>.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-square pf-system-security-1-0"></i></span> <samp>1-0</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-9"></i></span> <samp>0.9</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-8"></i></span> <samp>0.8</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-7"></i></span> <samp>0.7</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-6"></i></span> <samp>0.6</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-5"></i></span> <samp>0.5</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-4"></i></span> <samp>0.4</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-3"></i></span> <samp>0.3</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-2"></i></span> <samp>0.2</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-1"></i></span> <samp>0.1</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-0"></i></span> <samp>0.0 - -1.0</samp></li>
</ul>
<h4><i class="fas fa-chart-bar fa-fw"></i> Recent activity</h4><p>
<p>
The <em>"Recent activity"</em> bar chart is available for any active system <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small>.
The chart shows all ship kills in a system during the last <samp>24h</samp>. If <em class="pf-brand">pathfinder</em> detects recent kills (within the last hour), a small label is shown above the graph.
</p>
<div class="row">
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-align-left fa-fw"></i> Trade hub range</h4><p>
<p>
The <em>"Trade hub range"</em> table is available for any <em>"K-space"</em> system. Each row represents the jump distance to a main <em>"Trade-Hub"</em>.
Each system jump is represented by a <i class="fas fa-square fa-fw"></i> with the color of its <em>"Security status"</em> <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-security">more</a>)</small>.
</p>
<ul class="fa-ul">
<li><i class="fa-li fas fa-square pf-system-security-1-0"></i></span> <samp>1-0</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-9"></i></span> <samp>0.9</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-8"></i></span> <samp>0.8</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-7"></i></span> <samp>0.7</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-6"></i></span> <samp>0.6</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-5"></i></span> <samp>0.5</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-4"></i></span> <samp>0.4</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-3"></i></span> <samp>0.3</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-2"></i></span> <samp>0.2</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-1"></i></span> <samp>0.1</samp></li>
<li><i class="fa-li fas fa-square pf-system-security-0-0"></i></span> <samp>0.0 - -1.0</samp></li>
</ul>
</div>
<div class="col-xs-12 col-md-6">
<h4><i class="fas fa-chart-bar fa-fw"></i> Recent activity</h4><p>
<p>
The <em>"Recent activity"</em> bar chart is available for any active system <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small>.
The chart shows all ship kills in a system during the last <samp>24h</samp>. If <em class="pf-brand">pathfinder</em> detects recent kills (within the last hour), a small label is shown above the graph.
</p>
</div>
</div>
<hr class="pf-manual-scroll-break">
{{! ================================================================================================================================================ }}
@@ -502,10 +629,22 @@
<h4>Types</h4>
<div class="alert alert-success"><span class="txt-color txt-color-success">Success</span><small> (success message after pilot interaction)</small></div>
<div class="alert alert-info"><span class="txt-color txt-color-information">Info</span><small> (non-important additional information)</small></div>
<div class="alert alert-warning"><span class="txt-color txt-color-warning">Warning</span><small> (important non-critical information)</small></div>
<div class="alert alert-danger"><span class="txt-color txt-color-danger">Error</span><small> (very important information of error)</small></div>
<div class="row">
<div class="col-xs-12 col-md-6">
<div class="alert alert-success"><span class="txt-color txt-color-success">Success</span><small> (success message after pilot interaction)</small></div>
</div>
<div class="col-xs-12 col-md-6">
<div class="alert alert-info"><span class="txt-color txt-color-information">Info</span><small> (non-important additional information)</small></div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<div class="alert alert-warning"><span class="txt-color txt-color-warning">Warning</span><small> (important non-critical information)</small></div>
</div>
<div class="col-xs-12 col-md-6">
<div class="alert alert-danger"><span class="txt-color txt-color-danger">Error</span><small> (very important information of error)</small></div>
</div>
</div>
<h4 id="pf-manual-scrollspy-anchor-notification-desktop">Desktop push notifications</h4>
<p>
@@ -537,17 +676,25 @@
Map specific log settings can be changed for each map individually; see map settings dialog <small>(<i class="fas fa-cogs fa-fw"></i>)</small>.<br>
Some log methods might be globally disabled for some map types <small>(<i class="fas fa-sitemap fa-fw"></i><a href="#" data-target="#pf-manual-map">more</a>)</small>.
</p>
<h4><i class="far fa-file-code fa-fw"></i> Write log files</h4>
<p>
When enabled, <em class="pf-brand">pathfinder</em> will write a physical log file with map related events. There is UI in the "map information" dialog available (log file viewer).
</p>
<h4><i class="fab fa-slack-hash fa-fw"></i> Send logs to a <em>Slack</em> channel</h4>
<p>
Map logs can also be send to a <em>Slack</em> channel. This requires a valid "<em>WebHook</em>" configuration for your map.<br>
<em>Slack´s Webhook API</em> has bad response times, use this feature with caution! It can slow down other map updates.
</p>
<h4><i class="fab fa-discord fa-fw"></i> Send logs to a <em>Discord</em> channel</h4>
<p>
Map logs can also be send to a <em>Discord</em> channel. This requires a valid "<em>WebHook</em>" configuration for your map.<br>
</p>
<div class="row">
<div class="col-xs-12 col-md-4">
<h4><i class="far fa-file-code fa-fw"></i> Write log files</h4>
<p>
When enabled, <em class="pf-brand">pathfinder</em> will write a physical log file with map related events. There is UI in the "map information" dialog available (log file viewer).
</p>
</div>
<div class="col-xs-12 col-md-4">
<h4><i class="fab fa-slack-hash fa-fw"></i> Send logs to a <em>Slack</em> channel</h4>
<p>
Map logs can also be send to a <em>Slack</em> channel. This requires a valid "<em>WebHook</em>" configuration for your map.<br>
<em>Slack´s Webhook API</em> has bad response times, use this feature with caution! It can slow down other map updates.
</p>
</div>
<div class="col-xs-12 col-md-4">
<h4><i class="fab fa-discord fa-fw"></i> Send logs to a <em>Discord</em> channel</h4>
<p>
Map logs can also be send to a <em>Discord</em> channel. This requires a valid "<em>WebHook</em>" configuration for your map.<br>
</p>
</div>
</div>
</div>

View File

@@ -76,10 +76,10 @@
{{! wormhole ----------------------------------------------------------------- }}
<div class="row">
<div class="col-sm-4">
<div class="col-xs-12 col-sm-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 col-xs-6 checkbox checkbox-primary" title="include wormhole connections">
<div class="col-sm-12 checkbox checkbox-primary" title="include wormhole connections">
<input id="form_wormholes" name="wormholes" value="1" type="checkbox" checked>
<label for="form_wormholes">Wormholes</label>
</div>
@@ -87,10 +87,10 @@
</div>
</div>
<div class="col-sm-4">
<div class="col-xs-6 col-sm-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 col-xs-6 checkbox checkbox-warning checkbox-circle" title="include reduced connections">
<div class="col-sm-12 checkbox checkbox-warning checkbox-circle" title="include reduced connections">
<input id="form_wormholes_reduced" name="wormholesReduced" value="1" type="checkbox" checked>
<label for="form_wormholes_reduced">Stage 2 (reduced)</label>
</div>
@@ -98,10 +98,10 @@
</div>
</div>
<div class="col-sm-4">
<div class="col-xs-6 col-sm-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 col-xs-6 checkbox checkbox-danger checkbox-circle" title="include critical connections">
<div class="col-sm-12 checkbox checkbox-danger checkbox-circle" title="include critical connections">
<input id="form_wormholes_critical" name="wormholesCritical" value="1" type="checkbox" checked>
<label for="form_wormholes_critical">Stage 3 (critical)</label>
</div>
@@ -109,10 +109,10 @@
</div>
</div>
<div class="col-sm-4 col-sm-offset-4">
<div class="col-xs-6 col-sm-4 col-sm-offset-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 col-xs-6 checkbox checkbox checkbox-circle" title="include frigate connections">
<div class="col-sm-12 checkbox checkbox checkbox-circle" title="include frigate connections">
<input id="form_wormholes_frigate" name="wormholesFrigate" value="1" type="checkbox" checked>
<label for="form_wormholes_frigate">Frigate</label>
</div>
@@ -120,10 +120,10 @@
</div>
</div>
<div class="col-sm-4">
<div class="col-xs-6 col-sm-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 col-xs-6 checkbox checkbox-danger checkbox-circle" title="include EOL connections">
<div class="col-sm-12 checkbox checkbox-danger checkbox-circle" title="include EOL connections">
<input id="form_wormholes_eol" name="wormholesEOL" value="1" type="checkbox" checked>
<label for="form_wormholes_eol">End of life (EOL)</label>
</div>
@@ -132,5 +132,22 @@
</div>
</div>
<hr>
{{! endpoint ----------------------------------------------------------------- }}
<div class="row">
<div class="col-xs-6 col-sm-4">
<div class="form-group">
<div class="col-sm-offset-1 col-sm-11">
<div class="col-sm-12 checkbox checkbox-primary" title="include bubbled connections">
<input id="form_endpoints_bubble" name="endpointsBubble" value="1" type="checkbox" checked>
<label for="form_endpoints_bubble">Bubbled&nbsp;&nbsp;<span class="pf-endpoint-bubble"></span></label>
</div>
</div>
</div>
</div>
</div>
</form>
</div>

View File

@@ -35,6 +35,36 @@
}
};
// bubble =========================================================================================
@include keyframes(pfBubbleWobble){
from {
transform: scale(1, 1);
}
6.5% {
transform: scale(1, 1.4);
}
13% {
transform: scale(1.4, 1);
}
20% {
transform: scale(1, 1);
}
to {
transform: scale(1, 1);
}
}
@include keyframes(pfBubblePop){
from {
opacity: 1;
transform: translateZ(0) scale(1, 1);
}
to {
opacity: 0;
transform: translateZ(0) scale(1.75, 1.75);
}
}
// SVG pulse "fill" ===============================================================================
@include keyframes(pfPulseDanger){
0% {

View File

@@ -4,7 +4,7 @@
font-family: $font-family-sans-serif;
letter-spacing: 0;
font-size: $font-size-h5;
margin: 20px 0;
margin: 20px 0 10px 0;
line-height: normal;
}
@@ -189,6 +189,12 @@
position: relative;
height: 700px;
overflow: auto;
.list-unstyled.well{
display: inline-block;
}
}
// ad system dialog ===========================================================

View File

@@ -1,3 +1,5 @@
$endpointBubbleWidth: 18px;
body{
// prevent marking text
-webkit-touch-callout: none;
@@ -891,6 +893,23 @@ table{
color: $indigo;
}
// Connection Endpoint types ======================================================================
.pf-endpoint-bubble{
display: inline-block;
position: relative;
width: $endpointBubbleWidth;
height: $endpointBubbleWidth;
&:after{
content: url("#{$base-url}/bubble.svg");
display: inline-block;
pointer-events: none;
width: $endpointBubbleWidth;
height: $endpointBubbleWidth;
vertical-align: top;
}
}
// WH effects =====================================================================================
.pf-system-effect{
display: none; // if effect is active it will be overwritten

View File

@@ -1,35 +1,24 @@
$mapHeight: 1500px;
$mapWidth: 2500px;
$mapWrapperHeight: 520px + 35px;
$mapWrapperMinHeight: 250px;
$mapWrapperMaxHeight: 1000px; // no vertical scrollbar: $mapHeight + 35px;
$mapWrapperMaxWidth: $mapWidth + 35px;
$mapWrapperHeight: 520px + 35px;
$mapWrapperMinHeight: 250px;
$mapWrapperMaxHeight: 1000px; // no vertical scrollbar: $mapHeight + 35px;
$mapWrapperMaxWidth: $mapWidth + 35px;
$mapBubbleWidth: 30px;
// start bounce mixin =================================================================================================
@mixin bounce-up-down{
@include animation-duration( 1s);
@include animation-delay(0.5s);
-webkit-animation-fill-mode: both;
animation-duration: 1s;
animation-delay: 0.5s;
animation-fill-mode: both;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
animation-iteration-count:infinite;
-webkit-animation-iteration-count:infinite;
-webkit-animation-name: bounce;
animation-iteration-count: infinite;
animation-name: bounce;
}
@-webkit-keyframes bounce {
0%, 20%, 50%, 80%, 100% {-webkit-transform: translateY(0);}
40% {-webkit-transform: translateY(-8px);}
60% {-webkit-transform: translateY(-4px);}
}
@keyframes bounce {
@include keyframes(bounce){
0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
40% {transform: translateY(-8px);}
60% {transform: translateY(-4px);}
@@ -530,6 +519,15 @@ $mapWrapperMaxWidth: $mapWidth + 35px;
&.jsplumb-hover{
// increase z-index -> prevent overlapping multiple endpoints
z-index: 95;
&.pf-map-endpoint-bubble{
&:after{
filter: drop-shadow( -3px 3px 4px rgba(0,0,0, 0.3));
animation-iteration-count: infinite;
animation-delay: 0.5s;
animation-fill-mode: both;
}
}
}
// while dragging
@@ -554,6 +552,37 @@ $mapWrapperMaxWidth: $mapWidth + 35px;
}
}
.jsplumb-endpoint{
&:after{
content: url("#{$base-url}/bubble.svg");
position: absolute;
display: block;
pointer-events: none;
top: ($mapBubbleWidth / -2) + 5;
left: ($mapBubbleWidth / -2) + 5;
width: $mapBubbleWidth;
height: $mapBubbleWidth;
z-index: -1;
will-change: opacity, transform;
animation-name: pfBubblePop;
animation-duration: 0.09s;
animation-timing-function: cubic-bezier(0.16, 0.87, 0.48, 0.99);
animation-fill-mode: forwards;
animation-iteration-count: 1;
}
}
.pf-map-endpoint-bubble{
&:after{
display: block;
animation-name: pfBubbleWobble;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: 1;
}
}
// Connections ======================================================================================================
svg.jsplumb-connector{
@@ -741,11 +770,10 @@ $mapWrapperMaxWidth: $mapWidth + 35px;
// Endpoint overlays ================================================================================================
.pf-map-connection-small-overlay{
filter: blur(0.000001px);
-webkit-font-smoothing: antialiased;
font-family: Arial, sans-serif; // fix for element width on custom font family
padding: 2px;
font-size: 9.5px;
font-size: 10px;
line-height: 100%;
z-index: 1020;
background-color: $gray;