- new persistent map zoom level between sessions - improved wormhole type names. Color codes represent their target systems security level (green → HS, red → C5/6/0.0,…) - improved JS performance for map updates, signature updates, map zoom, map overlays - improved "manual" section for connections (size info added) - upgraded [_farahey_](https://github.com/jsplumb/farahey) js lib `v0.5` → `v1.1.2`
This commit is contained in:
@@ -155,7 +155,7 @@ class Route extends Controller\AccessController {
|
||||
}
|
||||
|
||||
if( $filterData['wormholesFrigate'] !== true ){
|
||||
$excludeTypes[] = 'frigate';
|
||||
$excludeTypes[] = 'wh_jump_mass_s';
|
||||
}
|
||||
|
||||
if( $filterData['wormholesEOL'] === false ){
|
||||
|
||||
@@ -401,8 +401,7 @@ class Sso extends Api\User{
|
||||
if( !empty($authCodeRequestData['expiresIn']) ){
|
||||
// expire time for accessToken
|
||||
try{
|
||||
$timezone = $this->getF3()->get('getTimeZone')();
|
||||
$accessTokenExpires = new \DateTime('now', $timezone);
|
||||
$accessTokenExpires = $this->getF3()->get('getDateTime')();
|
||||
$accessTokenExpires->add(new \DateInterval('PT' . (int)$authCodeRequestData['expiresIn'] . 'S'));
|
||||
|
||||
$accessData->esiAccessTokenExpires = $accessTokenExpires->format('Y-m-d H:i:s');
|
||||
|
||||
@@ -92,7 +92,23 @@ class ConnectionModel extends AbstractMapTrackingModel {
|
||||
* allowed connection types
|
||||
* @var array
|
||||
*/
|
||||
protected static $connectionTypeWhitelist = ['stargate', 'abyssal', 'wh_fresh', 'wh_reduced', 'wh_critical', 'frigate', 'preserve_mass'];
|
||||
protected static $connectionTypeWhitelist = [
|
||||
// base type for scopes
|
||||
'stargate',
|
||||
'abyssal',
|
||||
// wh mass reduction types
|
||||
'wh_fresh',
|
||||
'wh_reduced',
|
||||
'wh_critical',
|
||||
// wh jump mass types
|
||||
'wh_jump_mass_s',
|
||||
'wh_jump_mass_m',
|
||||
'wh_jump_mass_l',
|
||||
'wh_jump_mass_xl',
|
||||
// other types
|
||||
'wh_eol',
|
||||
'preserve_mass'
|
||||
];
|
||||
|
||||
/**
|
||||
* get connection data
|
||||
|
||||
@@ -658,7 +658,7 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
/**
|
||||
* @var $connection ConnectionModel
|
||||
*/
|
||||
$connectionData[] = $connection->getData();
|
||||
$connectionData[] = $connection->getData(true);
|
||||
}
|
||||
|
||||
return $connectionData;
|
||||
|
||||
@@ -812,7 +812,9 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* CharacterModel $character
|
||||
* Updates the signature history cache
|
||||
* -> each (bulk) change to signatures of this system must result in a new signature history cache entry
|
||||
* -> This method also clears the cache of this system, so that new signature data gets returned for in getData()
|
||||
* @param CharacterModel $character
|
||||
* @param string $action
|
||||
* @throws \Exception
|
||||
@@ -833,6 +835,11 @@ class SystemModel extends AbstractMapTrackingModel {
|
||||
array_splice($signaturesHistoryData, self::MAX_HISTORY_SIGNATURES);
|
||||
|
||||
$this->updateCacheData($signaturesHistoryData, self::DATA_CACHE_KEY_SIGNATURES, self::TTL_HISTORY_SIGNATURES);
|
||||
|
||||
// clear system cache here
|
||||
// -> Signature model updates should NOT update the system cache on change
|
||||
// because a "bulk" change to signatures would clear the system cache multiple times
|
||||
$this->clearCacheData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ requirejs.config({
|
||||
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
|
||||
slidebars: 'lib/slidebars', // v2.0.2 Slidebars - side menu plugin https://www.adchsm.com/slidebars/
|
||||
jsPlumb: 'lib/jsplumb', // v2.9.3 jsPlumb main map draw plugin http://jsplumb.github.io/jsplumb/home.html
|
||||
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey
|
||||
farahey: 'lib/farahey', // v1.1.2 jsPlumb "magnetizing" plugin extension - https://github.com/ThomasChan/farahey
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
|
||||
mousewheel: 'lib/jquery.mousewheel.min', // v3.1.13 Mousewheel - https://github.com/jquery/jquery-mousewheel
|
||||
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
|
||||
|
||||
@@ -145,7 +145,6 @@ define(['jquery'], ($) => {
|
||||
unicode: ''
|
||||
}
|
||||
],
|
||||
|
||||
classes: {
|
||||
// log types
|
||||
logTypes: {
|
||||
@@ -354,17 +353,61 @@ define(['jquery'], ($) => {
|
||||
wh_critical: {
|
||||
cssClass: 'pf-map-connection-wh-critical'
|
||||
},
|
||||
frigate: {
|
||||
cssClass: 'pf-map-connection-frig',
|
||||
wh_jump_mass_s: {
|
||||
cssClass: 'pf-map-connection-wh-size-s',
|
||||
paintStyle: {
|
||||
dashstyle: '0.5 1'
|
||||
dashstyle: '0.5 1',
|
||||
strokeWidth: 3
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: 'frig',
|
||||
cssClass: ['pf-map-component-overlay', 'frig'].join(' '),
|
||||
location: 0.7
|
||||
label: '<i class="fas fa-char pf-jump-mass-s" data-char-content="S"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_m: {
|
||||
cssClass: 'pf-map-connection-wh-size-m',
|
||||
paintStyle: {
|
||||
dashstyle: '3 1'
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-m" data-char-content="M"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_l: {
|
||||
cssClass: 'pf-map-connection-wh-size-l',
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-l" data-char-content="L"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_xl: {
|
||||
cssClass: 'pf-map-connection-wh-size-xl',
|
||||
paintStyle: {
|
||||
strokeWidth: 6
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-xl" data-char-content="XL"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
@@ -375,7 +418,7 @@ define(['jquery'], ($) => {
|
||||
{
|
||||
label: '<i class="fas fa-fw fa-exclamation-triangle"></i> save mass',
|
||||
cssClass: ['pf-map-component-overlay', 'mass'].join(' '),
|
||||
location: 0.3
|
||||
location: 0.35
|
||||
}]
|
||||
]
|
||||
},
|
||||
@@ -387,8 +430,8 @@ define(['jquery'], ($) => {
|
||||
cssClass: 'pf-map-connection-arrow-overlay',
|
||||
width: 12,
|
||||
length: 15,
|
||||
foldback: 0.8,
|
||||
direction: 1,
|
||||
foldback: 0.8,
|
||||
location: 0.5
|
||||
}]
|
||||
]
|
||||
@@ -408,6 +451,32 @@ define(['jquery'], ($) => {
|
||||
]
|
||||
}
|
||||
},
|
||||
wormholeSizes: {
|
||||
wh_jump_mass_xl: {
|
||||
jumpMassMin: 1000000000,
|
||||
type: 'wh_jump_mass_xl',
|
||||
class: 'pf-jump-mass-xl',
|
||||
label: 'XL'
|
||||
},
|
||||
wh_jump_mass_l: {
|
||||
jumpMassMin: 300000000,
|
||||
type: 'wh_jump_mass_l',
|
||||
class: 'pf-jump-mass-l',
|
||||
label: 'L'
|
||||
},
|
||||
wh_jump_mass_m: {
|
||||
jumpMassMin: 20000000,
|
||||
type: 'wh_jump_mass_m',
|
||||
class: 'pf-jump-mass-m',
|
||||
label: 'M'
|
||||
},
|
||||
wh_jump_mass_s: {
|
||||
jumpMassMin: 1000,
|
||||
type: 'wh_jump_mass_s',
|
||||
class: 'pf-jump-mass-s',
|
||||
label: 'S'
|
||||
}
|
||||
},
|
||||
// signature groups
|
||||
signatureGroups: {
|
||||
1: {
|
||||
|
||||
@@ -93,20 +93,25 @@ define([
|
||||
let moduleData = {
|
||||
id: config.connectionContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-plane', action: 'frigate', text: 'frigate hole'},
|
||||
{icon: 'fa-hourglass-end', action: 'wh_eol', text: 'toggle EOL'},
|
||||
{icon: 'fa-exclamation-triangle', action: 'preserve_mass', text: 'preserve mass'},
|
||||
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
|
||||
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'mass status', subitems: [
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-gray', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-orange', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-redDarker', subAction: 'status_critical', subText: 'stage 3 (critical)'}
|
||||
|
||||
]},
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'change status', subitems: [
|
||||
{subIcon: 'fa-clock', subAction: 'wh_eol', subText: 'toggle EOL'},
|
||||
{subDivider: true},
|
||||
{subIcon: 'fa-circle', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
|
||||
{subIcon: 'fa-adjust', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
|
||||
{subIcon: 'fa-circle', subAction: 'status_critical', subText: 'stage 3 (critical)'}
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'wh_jump_mass_change', text: 'ship size', subitems: [
|
||||
{subIcon: 'fa-char', subChar: 'S', subAction: 'wh_jump_mass_s', subText: 'smallest ships'},
|
||||
{subIcon: 'fa-char', subChar: 'M', subAction: 'wh_jump_mass_m', subText: 'medium ships'},
|
||||
{subIcon: 'fa-char', subChar: 'L', subAction: 'wh_jump_mass_l', subText: 'larger ships'},
|
||||
{subIcon: 'fa-char', subChar: 'XL', subAction: 'wh_jump_mass_xl', subText: 'capital ships'}
|
||||
|
||||
]},
|
||||
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
|
||||
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
|
||||
|
||||
]},
|
||||
{divider: true, action: 'separator'} ,
|
||||
|
||||
@@ -1,135 +1,173 @@
|
||||
/**
|
||||
* Map "magnetizing" feature
|
||||
* jsPlumb extension used: http://morrisonpitt.com/farahey/
|
||||
* jsPlumb extension used: https://github.com/ThomasChan/farahey
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/map/util',
|
||||
'farahey'
|
||||
], function($, MapUtil){
|
||||
], ($, MapUtil) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Cached current "Magnetizer" object
|
||||
* @type {Magnetizer}
|
||||
* active magnetizer instances (cache object)
|
||||
* @type {{}}
|
||||
*/
|
||||
let m8 = null;
|
||||
let magnetizerInstances = {};
|
||||
|
||||
/**
|
||||
* init a jsPlumb (map) Element for "magnetised" function.
|
||||
* this is optional and prevents systems from being overlapped
|
||||
* magnetizer instance exists for mapId
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$.fn.initMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
let systems = mapContainer.getSystems();
|
||||
let hasInstance = mapId => magnetizerInstances.hasOwnProperty(mapId);
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* get current system offset
|
||||
* @param system
|
||||
* @returns {{left, top}}
|
||||
* @private
|
||||
*/
|
||||
let _offset = function(system){
|
||||
/**
|
||||
* get magnetizer instance by mapId
|
||||
* @param mapId
|
||||
* @returns {null}
|
||||
*/
|
||||
let getInstance = mapId => hasInstance(mapId) ? magnetizerInstances[mapId] : null;
|
||||
|
||||
let _ = function(p){
|
||||
let v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
|
||||
return {
|
||||
left:_('left'),
|
||||
top:_('top')
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* set new system offset
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
let _setOffset = function(system, o){
|
||||
let markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 &&
|
||||
o.left <= 2300
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.left = o.left + 'px';
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 &&
|
||||
o.top <= 498
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.top = o.top + 'px';
|
||||
}
|
||||
|
||||
if(markAsUpdated === true){
|
||||
MapUtil.markAsChanged($(system));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* exclude current dragged element(s) from position update
|
||||
* @param id
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
let _dragFilter = function(id){
|
||||
return !$('#' + id).is('.jsPlumb_dragged, .pf-system-locked');
|
||||
};
|
||||
|
||||
let gridConstrain = function(gridX, gridY){
|
||||
return function(id, current, delta){
|
||||
if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){
|
||||
// active grid
|
||||
return {
|
||||
left:(gridX * Math.floor( (current[0] + delta.left) / gridX )) - current[0],
|
||||
top:(gridY * Math.floor( (current[1] + delta.top) / gridY )) - current[1]
|
||||
};
|
||||
}else{
|
||||
// no grid
|
||||
return delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// main init for "magnetize" feature ------------------------------------------------------
|
||||
m8 = new Magnetizer({
|
||||
container: mapContainer,
|
||||
getContainerPosition: function(c){
|
||||
return c.offset();
|
||||
},
|
||||
getPosition:_offset,
|
||||
getSize: function(system){
|
||||
return [ $(system).outerWidth(), $(system).outerHeight() ];
|
||||
},
|
||||
getId : function(system){
|
||||
return $(system).attr('id');
|
||||
},
|
||||
setPosition:_setOffset,
|
||||
elements: systems,
|
||||
filter: _dragFilter,
|
||||
padding: [6, 6],
|
||||
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension)
|
||||
});
|
||||
/**
|
||||
* set new magnetizer instance for mapId
|
||||
* @param mapId
|
||||
* @param magnetizer
|
||||
*/
|
||||
let setInstance = (mapId, magnetizer) => {
|
||||
if(mapId && magnetizer){
|
||||
magnetizerInstances[mapId] = magnetizer;
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.destroyMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
/**
|
||||
* init new magnetizer instance for a map
|
||||
* @param mapContainer
|
||||
*/
|
||||
let initMagnetizer = mapContainer => {
|
||||
let mapId = mapContainer.data('id');
|
||||
|
||||
// remove cached "magnetizer" instance
|
||||
m8 = null;
|
||||
if(!hasInstance(mapId)){
|
||||
// magnetizer not exist -> new instance
|
||||
let systems = mapContainer.getSystems();
|
||||
|
||||
/**
|
||||
* function that takes an element from your list and returns its position as a JS object
|
||||
* @param system
|
||||
* @returns {{top: number, left: number}}
|
||||
* @private
|
||||
*/
|
||||
let _offset = system => {
|
||||
let _ = p => {
|
||||
let v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
return {left: _('left'), top: _('top')};
|
||||
};
|
||||
|
||||
/**
|
||||
* function that takes an element id and position, and applies that position to the related element
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
let _setOffset = (system, o) => {
|
||||
o.left = Math.round(o.left);
|
||||
o.top = Math.round(o.top);
|
||||
let left = o.left + 'px';
|
||||
let top = o.top + 'px';
|
||||
let markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 && o.left <= 2300 &&
|
||||
system.style.left !== left
|
||||
){
|
||||
system.style.left = left;
|
||||
markAsUpdated = true;
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 && o.top <= 1400 &&
|
||||
system.style.top !== top
|
||||
){
|
||||
system.style.top = top;
|
||||
markAsUpdated = true;
|
||||
}
|
||||
|
||||
if(markAsUpdated){
|
||||
MapUtil.markAsChanged($(system));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* filter some element8s) from being moved
|
||||
* @param systemId
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
let _dragFilter = systemId => {
|
||||
let filterClasses = ['jtk-drag', 'pf-system-locked'];
|
||||
return ![...document.getElementById(systemId).classList].some(className => filterClasses.indexOf(className) >= 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* grid snap constraint
|
||||
* @param gridX
|
||||
* @param gridY
|
||||
* @returns {Function}
|
||||
*/
|
||||
let gridConstrain = (gridX, gridY) => {
|
||||
return (id, current, delta) => {
|
||||
if(mapContainer.hasClass(MapUtil.config.mapGridClass)){
|
||||
// active grid
|
||||
return {
|
||||
left: (gridX * Math.floor( (Math.round(current[0]) + delta.left) / gridX )) - current[0],
|
||||
top: (gridY * Math.floor( (Math.round(current[1]) + delta.top) / gridY )) - current[1]
|
||||
};
|
||||
}else{
|
||||
// no grid
|
||||
delta.left = Math.round(delta.left);
|
||||
delta.top = Math.round(delta.top);
|
||||
return delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// create new magnetizer instance -------------------------------------------------------------------------
|
||||
setInstance(mapId, window.Farahey.getInstance({
|
||||
container: mapContainer,
|
||||
getContainerPosition: mapContainer => mapContainer.offset(),
|
||||
getPosition:_offset,
|
||||
getSize: system => {
|
||||
let clientRect = system.getBoundingClientRect();
|
||||
return [Math.floor(clientRect.width), Math.floor(clientRect.height)];
|
||||
},
|
||||
getId : system => system.id,
|
||||
setPosition:_setOffset,
|
||||
elements: systems.toArray(),
|
||||
filter: _dragFilter,
|
||||
padding: [3, 3],
|
||||
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension),
|
||||
executeNow: false, // no initial rearrange after initialization
|
||||
excludeFocus: true
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* destroy Magnetizer instance
|
||||
*/
|
||||
let destroyMagnetizer = mapContainer => {
|
||||
let mapId = mapContainer.data('id');
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.reset();
|
||||
delete magnetizerInstances[mapId];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -137,44 +175,50 @@ define([
|
||||
* @param map
|
||||
* @param e
|
||||
*/
|
||||
let executeAtEvent = function(map, e){
|
||||
if(m8 !== null && e ){
|
||||
m8.executeAtEvent(e);
|
||||
let executeAtEvent = (map, e) => {
|
||||
let mapContainer = $(map.getContainer());
|
||||
let mapId = mapContainer.data('id');
|
||||
let magnetizer = getInstance(mapId);
|
||||
|
||||
if(magnetizer && e){
|
||||
magnetizer.executeAtEvent(e, {
|
||||
iterations: 2,
|
||||
excludeFocus: true
|
||||
});
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* rearrange all systems of a map
|
||||
* needs "magnetization" to be active
|
||||
* @param map
|
||||
* add system to magnetizer instance
|
||||
* @param mapId
|
||||
* @param system
|
||||
* @param doNotTestForDuplicates
|
||||
*/
|
||||
let executeAtCenter = function(map){
|
||||
if(m8 !== null){
|
||||
m8.executeAtCenter();
|
||||
map.repaintEverything();
|
||||
let addElement = (mapId, system, doNotTestForDuplicates) => {
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.addElement(system, doNotTestForDuplicates);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set/update elements for "magnetization"
|
||||
* -> (e.g. new systems was added)
|
||||
* @param map
|
||||
* remove system element from magnetizer instance
|
||||
* @param mapId
|
||||
* @param system
|
||||
*/
|
||||
let setElements = function(map){
|
||||
if(m8 !== null){
|
||||
let mapContainer = $(map.getContainer());
|
||||
let systems = mapContainer.getSystems();
|
||||
m8.setElements(systems);
|
||||
|
||||
// re-arrange systems
|
||||
executeAtCenter(map);
|
||||
let removeElement = (mapId, system) => {
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.removeElement(system);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
executeAtCenter: executeAtCenter,
|
||||
initMagnetizer: initMagnetizer,
|
||||
destroyMagnetizer: destroyMagnetizer,
|
||||
executeAtEvent: executeAtEvent,
|
||||
setElements: setElements
|
||||
addElement: addElement,
|
||||
removeElement: removeElement
|
||||
};
|
||||
});
|
||||
@@ -18,7 +18,7 @@ define([
|
||||
'app/map/scrollbar',
|
||||
'dragToSelect',
|
||||
'app/map/local'
|
||||
], ($, Init, Util, Key, bootbox, MapUtil, MapContextMenu, MapOverlay, MapOverlayUtil, System, Layout, MagnetizerWrapper, Scrollbar) => {
|
||||
], ($, Init, Util, Key, bootbox, MapUtil, MapContextMenu, MapOverlay, MapOverlayUtil, System, Layout, Magnetizer, Scrollbar) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -62,6 +62,33 @@ define([
|
||||
// -> those maps queue their updates until "pf:unlocked" event
|
||||
let mapUpdateQueue = [];
|
||||
|
||||
|
||||
// map menu options
|
||||
let mapOptions = {
|
||||
mapMagnetizer: {
|
||||
buttonId: Util.config.menuButtonMagnetizerId,
|
||||
description: 'Magnetizer',
|
||||
onEnable: Magnetizer.initMagnetizer,
|
||||
onDisable: Magnetizer.destroyMagnetizer
|
||||
},
|
||||
mapSnapToGrid : {
|
||||
buttonId: Util.config.menuButtonGridId,
|
||||
description: 'Grid snapping',
|
||||
class: 'mapGridClass'
|
||||
},
|
||||
mapSignatureOverlays : {
|
||||
buttonId: Util.config.menuButtonEndpointId,
|
||||
description: 'Endpoint overlay',
|
||||
onEnable: MapOverlay.showInfoSignatureOverlays,
|
||||
onDisable: MapOverlay.hideInfoSignatureOverlays,
|
||||
},
|
||||
mapCompact : {
|
||||
buttonId: Util.config.menuButtonCompactId,
|
||||
description: 'Compact system layout',
|
||||
class: 'mapCompactClass'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* checks mouse events on system head elements
|
||||
* -> prevents drag/drop system AND drag/drop connections on some child elements
|
||||
@@ -131,8 +158,8 @@ define([
|
||||
// check if there is a Label overlay
|
||||
let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
|
||||
if(overlay instanceof jsPlumb.Overlays.Label){
|
||||
let label = overlay.getParameter('label');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
|
||||
let labels = overlay.getParameter('signatureLabels');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,7 +702,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// save filterScopes in IndexDB
|
||||
// store filterScopes in IndexDB
|
||||
MapUtil.storeLocalData('map', mapId, 'filterScopes', filterScopes);
|
||||
MapUtil.filterMapByScopes(map, filterScopes);
|
||||
|
||||
@@ -726,7 +753,6 @@ define([
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'frigate': // set as frigate hole
|
||||
case 'preserve_mass': // set "preserve mass
|
||||
case 'wh_eol': // set "end of life"
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
|
||||
@@ -741,6 +767,14 @@ define([
|
||||
MapUtil.setConnectionWHStatus(connection, 'wh_' + newStatus);
|
||||
MapUtil.markAsChanged(connection);
|
||||
break;
|
||||
case 'wh_jump_mass_s':
|
||||
case 'wh_jump_mass_m':
|
||||
case 'wh_jump_mass_l':
|
||||
case 'wh_jump_mass_xl':
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
|
||||
MapUtil.setConnectionJumpMassType(connection, action);
|
||||
MapUtil.markAsChanged(connection);
|
||||
break;
|
||||
case 'scope_wh':
|
||||
case 'scope_stargate':
|
||||
case 'scope_jumpbridge':
|
||||
@@ -969,13 +1003,13 @@ define([
|
||||
if(checkAvailability(['fresh', 'reduced', 'critical'], type)){
|
||||
MapUtil.setConnectionWHStatus(connection, type);
|
||||
}else if(connection.hasType(type) !== true){
|
||||
// additional types e.g. eol, frig, preserve mass
|
||||
// additional types e.g. eol, preserve mass
|
||||
connection.addType(type);
|
||||
}
|
||||
}
|
||||
|
||||
for(let type of removeType){
|
||||
if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass', 'state_process'], type)){
|
||||
if(checkAvailability(['wh_eol', 'preserve_mass', 'state_process'], type)){
|
||||
connection.removeType(type);
|
||||
}
|
||||
}
|
||||
@@ -1178,7 +1212,6 @@ define([
|
||||
let mapContainer = mapConfig.map ? $(mapConfig.map.getContainer()) : null;
|
||||
if(mapContainer){
|
||||
let mapId = mapConfig.config.id;
|
||||
let newSystems = 0;
|
||||
|
||||
// add additional information for this map
|
||||
if(mapContainer.data('updated') !== mapConfig.config.updated.updated){
|
||||
@@ -1219,9 +1252,8 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
if( addNewSystem === true){
|
||||
if(addNewSystem === true){
|
||||
drawSystem(mapConfig.map, systemData);
|
||||
newSystems++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1324,11 +1356,6 @@ define([
|
||||
|
||||
// update local connection cache
|
||||
updateConnectionsCache(mapConfig.map);
|
||||
|
||||
// update map "magnetization" when new systems where added
|
||||
if(newSystems > 0){
|
||||
MagnetizerWrapper.setElements(mapConfig.map);
|
||||
}
|
||||
}else{
|
||||
// map is currently logged -> queue update for this map until unlock
|
||||
if( mapUpdateQueue.indexOf(mapId) === -1 ){
|
||||
@@ -1345,10 +1372,13 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(updateMapExecutor).then(payload => {
|
||||
|
||||
/**
|
||||
* apply current active scope filter
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let filterMapByScopes = payload => {
|
||||
let filterMapByScopesExecutor = (resolve, reject) => {
|
||||
// apply current active scope filter ==================================================================
|
||||
let promiseStore = MapUtil.getLocaleData('map', payload.data.mapConfig.config.id);
|
||||
promiseStore.then(dataStore => {
|
||||
let scopes = [];
|
||||
@@ -1362,7 +1392,31 @@ define([
|
||||
};
|
||||
|
||||
return new Promise(filterMapByScopesExecutor);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show signature overlays
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let showInfoSignatureOverlays = payload => {
|
||||
let showInfoSignatureOverlaysExecutor = (resolve, reject) => {
|
||||
let promiseStore = MapUtil.getLocaleData('map', payload.data.mapConfig.config.id);
|
||||
promiseStore.then(dataStore => {
|
||||
if(dataStore && dataStore.mapSignatureOverlays){
|
||||
MapOverlay.showInfoSignatureOverlays($(payload.data.mapConfig.map.getContainer()));
|
||||
}
|
||||
|
||||
resolve(payload);
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(showInfoSignatureOverlaysExecutor);
|
||||
};
|
||||
|
||||
return new Promise(updateMapExecutor)
|
||||
.then(showInfoSignatureOverlays)
|
||||
.then(filterMapByScopes);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1504,6 +1558,9 @@ define([
|
||||
// set system observer
|
||||
setSystemObserver(map, newSystem);
|
||||
|
||||
// register system to "magnetizer"
|
||||
Magnetizer.addElement(systemData.mapId, newSystem[0]);
|
||||
|
||||
// connect new system (if connection data is given)
|
||||
if(connectedSystem){
|
||||
|
||||
@@ -1736,22 +1793,26 @@ define([
|
||||
|
||||
// hidden menu actions
|
||||
if(scope === 'abyssal'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('change_scope');
|
||||
options.hidden.push('separator');
|
||||
}else if(scope === 'stargate'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('scope_stargate');
|
||||
}else if(scope === 'jumpbridge'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('scope_jumpbridge');
|
||||
}else if(scope === 'wh'){
|
||||
options.hidden.push('scope_wh');
|
||||
@@ -1761,13 +1822,14 @@ define([
|
||||
if(connection.hasType('wh_eol') === true){
|
||||
options.active.push('wh_eol');
|
||||
}
|
||||
|
||||
if(connection.hasType('frigate') === true){
|
||||
options.active.push('frigate');
|
||||
}
|
||||
if(connection.hasType('preserve_mass') === true){
|
||||
options.active.push('preserve_mass');
|
||||
}
|
||||
for(let sizeName of Object.keys(Init.wormholeSizes)){
|
||||
if(connection.hasType(sizeName)){
|
||||
options.active.push(sizeName);
|
||||
}
|
||||
}
|
||||
if(connection.hasType('wh_reduced') === true){
|
||||
options.active.push('status_reduced');
|
||||
}else if(connection.hasType('wh_critical') === true){
|
||||
@@ -1777,6 +1839,11 @@ define([
|
||||
options.active.push('status_fresh');
|
||||
}
|
||||
|
||||
// disabled menu actions
|
||||
if(connection.getParameter('sizeLocked')){
|
||||
options.disabled.push('wh_jump_mass_change');
|
||||
}
|
||||
|
||||
resolve(options);
|
||||
};
|
||||
|
||||
@@ -1864,7 +1931,7 @@ define([
|
||||
|
||||
// update system positions for "all" systems that are effected by drag&drop
|
||||
// this requires "magnet" feature to be active! (optional)
|
||||
MagnetizerWrapper.executeAtEvent(map, p.e);
|
||||
Magnetizer.executeAtEvent(map, p.e);
|
||||
},
|
||||
stop: function(params){
|
||||
let dragSystem = $(params.el);
|
||||
@@ -1967,11 +2034,7 @@ define([
|
||||
* @param sourceSystem
|
||||
*/
|
||||
let saveSystemCallback = (map, newSystemData, sourceSystem) => {
|
||||
// draw new system to map
|
||||
drawSystem(map, newSystemData, sourceSystem);
|
||||
|
||||
// re/arrange systems (prevent overlapping)
|
||||
MagnetizerWrapper.setElements(map);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2224,6 +2287,13 @@ define([
|
||||
// Notification the current zoom was changed
|
||||
newJsPlumbInstance.bind('zoom', function(zoom){
|
||||
MapOverlay.updateZoomOverlay(this);
|
||||
|
||||
// store new zoom level in IndexDB
|
||||
if(zoom === 1){
|
||||
MapUtil.deleteLocalData('map', mapId, 'mapZoom');
|
||||
}else{
|
||||
MapUtil.storeLocalData('map', mapId, 'mapZoom', zoom);
|
||||
}
|
||||
});
|
||||
|
||||
// ========================================================================================================
|
||||
@@ -2523,7 +2593,7 @@ define([
|
||||
let mapElement = $(this);
|
||||
|
||||
// get map menu config options
|
||||
let data = MapUtil.mapOptions[mapOption.option];
|
||||
let data = mapOptions[mapOption.option];
|
||||
|
||||
let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(function(dataStore){
|
||||
@@ -2538,50 +2608,50 @@ define([
|
||||
dataExists = true;
|
||||
}
|
||||
|
||||
if(dataExists === mapOption.toggle){
|
||||
if(dataExists === this.mapOption.toggle){
|
||||
|
||||
// toggle button class
|
||||
button.removeClass('active');
|
||||
|
||||
// toggle map class (e.g. for grid)
|
||||
if(this.data.class){
|
||||
this.mapElement.removeClass( MapUtil.config[this.data.class] );
|
||||
this.mapElement.removeClass(MapUtil.config[this.data.class]);
|
||||
}
|
||||
|
||||
// call optional jQuery extension on mapElement
|
||||
if(this.data.onDisable){
|
||||
$.fn[ this.data.onDisable ].apply(this.mapElement);
|
||||
if(this.data.onDisable && !this.mapOption.skipOnDisable){
|
||||
this.data.onDisable(this.mapElement);
|
||||
}
|
||||
|
||||
// show map overlay info icon
|
||||
MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'hide');
|
||||
|
||||
// delete map option
|
||||
MapUtil.deleteLocalData('map', this.mapElement.data('id'), this.mapOption.option );
|
||||
MapUtil.deleteLocalData('map', this.mapElement.data('id'), this.mapOption.option);
|
||||
}else{
|
||||
// toggle button class
|
||||
button.addClass('active');
|
||||
|
||||
// toggle map class (e.g. for grid)
|
||||
if(this.data.class){
|
||||
this.mapElement.addClass( MapUtil.config[this.data.class] );
|
||||
this.mapElement.addClass(MapUtil.config[this.data.class]);
|
||||
}
|
||||
|
||||
// call optional jQuery extension on mapElement
|
||||
if(this.data.onEnable){
|
||||
$.fn[ this.data.onEnable ].apply(this.mapElement);
|
||||
if(this.data.onEnable && !this.mapOption.skipOnEnable){
|
||||
this.data.onEnable(this.mapElement);
|
||||
}
|
||||
|
||||
// hide map overlay info icon
|
||||
MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'show');
|
||||
|
||||
// store map option
|
||||
MapUtil.storeLocalData('map', this.mapElement.data('id'), this.mapOption.option, 1 );
|
||||
MapUtil.storeLocalData('map', this.mapElement.data('id'), this.mapOption.option, 1);
|
||||
|
||||
notificationText = 'enabled';
|
||||
}
|
||||
|
||||
if(mapOption.toggle){
|
||||
if(this.mapOption.toggle){
|
||||
Util.showNotify({title: this.data.description, text: notificationText, type: 'info'});
|
||||
}
|
||||
}.bind({
|
||||
@@ -3009,7 +3079,8 @@ define([
|
||||
let mapElement = $(mapConfig.map.getContainer());
|
||||
MapUtil.setMapDefaultOptions(mapElement, mapConfig.config)
|
||||
.then(payload => MapUtil.visualizeMap(mapElement, 'show'))
|
||||
.then(payload => MapUtil.scrollToDefaultPosition(mapElement))
|
||||
.then(payload => MapUtil.zoomToDefaultScale(mapConfig.map))
|
||||
.then(payload => MapUtil.scrollToDefaultPosition(mapConfig.map))
|
||||
.then(payload => {
|
||||
Util.showNotify({title: 'Map initialized', text: mapConfig.config.name + ' - loaded', type: 'success'});
|
||||
})
|
||||
@@ -3039,7 +3110,7 @@ define([
|
||||
*/
|
||||
let loadMapExecutor = (resolve, reject) => {
|
||||
// init jsPlumb
|
||||
jsPlumb.ready(function(){
|
||||
jsPlumb.ready(() => {
|
||||
// get new map instance or load existing
|
||||
mapConfig.map = getMapInstance(mapConfig.config.id);
|
||||
|
||||
|
||||
@@ -11,81 +11,93 @@ define([
|
||||
], ($, Init, Util, MapOverlayUtil, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* get MapObject (jsPlumb) from mapElement
|
||||
* @param mapElement
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromMapElement = mapElement => {
|
||||
let Map = require('app/map/map');
|
||||
return Map.getMapInstance(mapElement.data('id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* get map object (jsPlumb) from iconElement
|
||||
* @param overlayIcon
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromOverlayIcon = overlayIcon => {
|
||||
let mapElement = Util.getMapElementFromOverlay(overlayIcon);
|
||||
return getMapObjectFromMapElement(mapElement);
|
||||
return MapUtil.getMapInstance(Util.getMapElementFromOverlay(overlayIcon).data('id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlay to endpoint with signature data
|
||||
* add/update endpoints with overlays from signature mapping
|
||||
* @param endpoint
|
||||
* @param labelData
|
||||
*/
|
||||
let addEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let label = labelData.labels.join(', ');
|
||||
let name = labelData.names.join(', ');
|
||||
let updateEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let labels = labelData.labels;
|
||||
let names = labelData.names;
|
||||
let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
|
||||
|
||||
if(overlay instanceof jsPlumb.Overlays.Label){
|
||||
// update existing overlay
|
||||
if(
|
||||
label !== overlay.getParameter('label') ||
|
||||
name !== overlay.getParameter('signatureName')
|
||||
!labels.equalValues(overlay.getParameter('signatureLabels')) ||
|
||||
!names.equalValues(overlay.getParameter('signatureNames'))
|
||||
){
|
||||
// update label only on label changes
|
||||
overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(label));
|
||||
overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(labels));
|
||||
overlay.setParameter('fullSize', false);
|
||||
overlay.setParameter('label', label);
|
||||
overlay.setParameter('signatureName', name);
|
||||
overlay.updateClasses(label.length ? 'small' : 'icon', label.length ? 'icon' : 'small');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
|
||||
overlay.setParameter('signatureLabels', labels);
|
||||
overlay.setParameter('signatureNames', names);
|
||||
overlay.updateClasses(labels.length ? 'small' : 'icon', labels.length ? 'icon' : 'small');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels));
|
||||
}
|
||||
}else{
|
||||
// add new overlay
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(label),
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(labels),
|
||||
id: MapOverlayUtil.config.endpointOverlayId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, labels.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels),
|
||||
events: {
|
||||
toggleSize: function(fullSize){
|
||||
let signatureName = this.getParameter('signatureName');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureName){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureName + '</span>');
|
||||
let signatureNames = this.getParameter('signatureNames');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureNames.length){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureNames.join(', ') + '</span>');
|
||||
this.setParameter('fullSize', true);
|
||||
}else if(this.getParameter('fullSize')){
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('signatureLabels')));
|
||||
this.setParameter('fullSize', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
fullSize: false,
|
||||
label: label,
|
||||
signatureName: name
|
||||
signatureLabels: labels,
|
||||
signatureNames: names
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get overlay parameters for connection overlay (type 'diamond' or 'arrow')
|
||||
* @param overlayType
|
||||
* @param direction
|
||||
* @returns {{length: number, foldback: number, direction: number}}
|
||||
*/
|
||||
let getConnectionArrowOverlayParams = (overlayType, direction = 1) => {
|
||||
switch(overlayType){
|
||||
case 'arrow':
|
||||
return {
|
||||
length: 15,
|
||||
direction: direction,
|
||||
foldback: 0.8
|
||||
};
|
||||
default: // diamond
|
||||
return {
|
||||
length: 10,
|
||||
direction: 1,
|
||||
foldback: 2
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlays to connections (signature based data)
|
||||
* @param map
|
||||
@@ -93,26 +105,18 @@ define([
|
||||
*/
|
||||
let updateInfoSignatureOverlays = (map, connectionsData) => {
|
||||
let type = 'info_signature';
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
|
||||
connectionsData = Util.arrayToObject(connectionsData);
|
||||
|
||||
map.batch(function(){
|
||||
map.getAllConnections().forEach(function(connection){
|
||||
map.batch(() => {
|
||||
map.getAllConnections().forEach(connection => {
|
||||
let connectionId = connection.getParameter('connectionId');
|
||||
let sourceEndpoint = connection.endpoints[0];
|
||||
let targetEndpoint = connection.endpoints[1];
|
||||
|
||||
let signatureTypeData = {
|
||||
source: {
|
||||
names: [],
|
||||
labels: []
|
||||
},
|
||||
target: {
|
||||
names: [],
|
||||
labels: []
|
||||
}
|
||||
};
|
||||
let connectionData = connectionsData.hasOwnProperty(connectionId) ? connectionsData[connectionId] : undefined;
|
||||
let signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sizeLockedBySignature = false;
|
||||
|
||||
if(connection.scope === 'wh'){
|
||||
if(!connection.hasType(type)){
|
||||
@@ -127,49 +131,49 @@ define([
|
||||
connection.canvas.appendChild(overlayArrow.path);
|
||||
}
|
||||
|
||||
let overlayType = 'Diamond'; // not specified
|
||||
// since there "could" be multiple sig labels on each endpoint,
|
||||
// there can only one "primary label picked up for wormhole jump mass detection!
|
||||
let primLabel;
|
||||
|
||||
let overlayType = 'diamond'; // not specified
|
||||
let arrowDirection = 1;
|
||||
let arrowFoldback = 2;
|
||||
|
||||
if(connectionsData.hasOwnProperty(connectionId)){
|
||||
if(connectionData && connectionData.signatures){
|
||||
// signature data found for current connection
|
||||
signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionsData[connectionId]);
|
||||
|
||||
let sourceLabel = signatureTypeData.source.labels;
|
||||
let targetLabel = signatureTypeData.target.labels;
|
||||
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ------------------------------------
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ----------------------------
|
||||
if(
|
||||
(sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.includes('K162') && targetLabel.includes('K162')) ||
|
||||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
|
||||
(
|
||||
sourceLabel.length > 0 && targetLabel.length > 0 &&
|
||||
sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
|
||||
!sourceLabel.includes('K162') && !targetLabel.includes('K162')
|
||||
)
|
||||
){
|
||||
// unknown direction
|
||||
overlayType = 'Diamond'; // not specified
|
||||
arrowDirection = 1;
|
||||
arrowFoldback = 2;
|
||||
// unknown direction -> show default 'diamond' overlay
|
||||
overlayType = 'diamond';
|
||||
}else if(
|
||||
(sourceLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
|
||||
(sourceLabel.includes('K162')) ||
|
||||
(sourceLabel.length === 0 && !targetLabel.includes('K162'))
|
||||
){
|
||||
// convert default arrow direction
|
||||
overlayType = 'Arrow';
|
||||
overlayType = 'arrow';
|
||||
arrowDirection = -1;
|
||||
arrowFoldback = 0.8;
|
||||
|
||||
primLabel = targetLabel.find(label => label !== 'K162');
|
||||
}else{
|
||||
// default arrow direction is fine
|
||||
overlayType = 'Arrow';
|
||||
arrowDirection = 1;
|
||||
arrowFoldback = 0.8;
|
||||
overlayType = 'arrow';
|
||||
|
||||
primLabel = sourceLabel.find(label => label !== 'K162');
|
||||
}
|
||||
}
|
||||
|
||||
// class changes must be done on "connection" itself not on "overlayArrow"
|
||||
// -> because Arrow might not be rendered to map at this point (if it does not exist already)
|
||||
if(overlayType === 'Arrow'){
|
||||
if(overlayType === 'arrow'){
|
||||
connection.updateClasses(
|
||||
MapOverlayUtil.config.connectionArrowOverlaySuccessClass,
|
||||
MapOverlayUtil.config.connectionArrowOverlayDangerClass
|
||||
@@ -181,20 +185,39 @@ define([
|
||||
);
|
||||
}
|
||||
|
||||
overlayArrow.updateFrom({
|
||||
direction: arrowDirection,
|
||||
foldback: arrowFoldback
|
||||
});
|
||||
overlayArrow.updateFrom(getConnectionArrowOverlayParams(overlayType, arrowDirection));
|
||||
|
||||
// add endpoint overlays --------------------------------------------------------------------------
|
||||
addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
// update/add endpoint overlays -------------------------------------------------------------------
|
||||
updateEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
updateEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
|
||||
// fix/overwrite existing jump mass connection type -----------------------------------------------
|
||||
// if a connection type for "jump mass" (e.g. S, M, L, XL) is set for this connection
|
||||
// we should check/compare it with the current primary signature label from signature mapping
|
||||
// and change it if necessary
|
||||
if(Init.wormholes.hasOwnProperty(primLabel)){
|
||||
// connection size from mapped signature
|
||||
sizeLockedBySignature = true;
|
||||
|
||||
let wormholeData = Object.assign({}, Init.wormholes[primLabel]);
|
||||
if(
|
||||
wormholeData.size && wormholeData.size.type &&
|
||||
!connection.hasType(wormholeData.size.type)
|
||||
){
|
||||
MapOverlayUtil.getMapOverlay(connection.canvas, 'timer').startMapUpdateCounter();
|
||||
MapUtil.setConnectionJumpMassType(connection, wormholeData.size.type);
|
||||
MapUtil.markAsChanged(connection);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// connection is not 'wh' scope
|
||||
if(connection.hasType(type)){
|
||||
connection.removeType(type);
|
||||
}
|
||||
}
|
||||
|
||||
// lock/unlock connection for manual size changes (from contextmenu)
|
||||
connection.setParameter('sizeLocked', sizeLockedBySignature);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -246,58 +269,45 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* git signature data that is linked to a connection for a mapId
|
||||
* @param mapElement
|
||||
* @param callback
|
||||
* get overlay icon from e.g. mapElement
|
||||
* @param element
|
||||
* @param iconClass
|
||||
* @param overlayType
|
||||
* @returns {*}
|
||||
*/
|
||||
let getConnectionSignatureData = (mapElement, callback) => {
|
||||
let mapOverlay = MapOverlayUtil.getMapOverlay(mapElement, 'info');
|
||||
let overlayConnectionIcon = mapOverlay.find('.pf-map-overlay-endpoint');
|
||||
|
||||
showLoading(overlayConnectionIcon);
|
||||
|
||||
let requestData = {
|
||||
mapId: mapElement.data('id'),
|
||||
addData : ['signatures'],
|
||||
filterData : ['signatures']
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getMapConnectionData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
mapElement: mapElement,
|
||||
overlayConnectionIcon: overlayConnectionIcon
|
||||
}
|
||||
}).done(function(connectionsData){
|
||||
let map = getMapObjectFromMapElement(this.mapElement);
|
||||
callback(map, connectionsData);
|
||||
}).always(function(){
|
||||
hideLoading(this.overlayConnectionIcon);
|
||||
});
|
||||
let getOverlayIcon = (element, iconClass, overlayType = 'info') => {
|
||||
return MapOverlayUtil.getMapOverlay(element, overlayType).find('.' + iconClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* showInfoSignatureOverlays
|
||||
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
|
||||
*/
|
||||
$.fn.showInfoSignatureOverlays = function(){
|
||||
let mapElement = $(this);
|
||||
getConnectionSignatureData(mapElement, updateInfoSignatureOverlays);
|
||||
let showInfoSignatureOverlays = mapElement => {
|
||||
let mapId = mapElement.data('id');
|
||||
let map = MapUtil.getMapInstance(mapId);
|
||||
let mapData = Util.getCurrentMapData(mapId);
|
||||
let connectionsData = Util.getObjVal(mapData, 'data.connections');
|
||||
|
||||
if(connectionsData){
|
||||
let overlayIcon = getOverlayIcon(mapElement, options.mapSignatureOverlays.class);
|
||||
showLoading(overlayIcon);
|
||||
updateInfoSignatureOverlays(map, connectionsData);
|
||||
hideLoading(overlayIcon);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hideInfoSignatureOverlays
|
||||
* -> see showInfoSignatureOverlays()
|
||||
*/
|
||||
$.fn.hideInfoSignatureOverlays = function(){
|
||||
let map = getMapObjectFromMapElement($(this));
|
||||
let hideInfoSignatureOverlays = mapElement => {
|
||||
let mapId = mapElement.data('id');
|
||||
let map = MapUtil.getMapInstance(mapId);
|
||||
let type = 'info_signature';
|
||||
|
||||
map.batch(function(){
|
||||
map.getAllConnections().forEach(function(connection){
|
||||
map.batch(() => {
|
||||
map.getAllConnections().forEach(connection => {
|
||||
let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
|
||||
if(overlayArrow){
|
||||
@@ -382,20 +392,11 @@ define([
|
||||
}
|
||||
}
|
||||
},
|
||||
mapEndpoint: {
|
||||
mapSignatureOverlays: {
|
||||
title: 'refresh signature overlays',
|
||||
trigger: 'refresh',
|
||||
class: 'pf-map-overlay-endpoint',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-link'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
mapElement.showInfoSignatureOverlays();
|
||||
},
|
||||
out: function(e){
|
||||
// just "refresh" on hover
|
||||
}
|
||||
}
|
||||
iconClass: ['fas', 'fa-fw', 'fa-link']
|
||||
},
|
||||
mapCompact: {
|
||||
title: 'compact layout',
|
||||
@@ -427,8 +428,8 @@ define([
|
||||
|
||||
// format overlay label
|
||||
let labels = [
|
||||
'<i class="fas fa-fw fa-plus-square"></i> ' + formatTimeParts(createdDiff),
|
||||
'<i class="fas fa-fw fa-pen-square"></i> ' + formatTimeParts(updatedDiff)
|
||||
formatTimeParts(createdDiff) + ' <i class="fas fa-fw fa-plus-square"></i>',
|
||||
formatTimeParts(updatedDiff) + ' <i class="fas fa-fw fa-pen-square"></i>'
|
||||
];
|
||||
|
||||
// add label overlay --------------------------------------------------------------------------
|
||||
@@ -437,7 +438,7 @@ define([
|
||||
{
|
||||
label: labels.join('<br>'),
|
||||
id: MapOverlayUtil.config.connectionOverlayWhId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small'].join(' '),
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small', 'text-right'].join(' '),
|
||||
location: 0.35
|
||||
}
|
||||
]);
|
||||
@@ -457,7 +458,7 @@ define([
|
||||
title: 'EOL timer',
|
||||
trigger: 'hover',
|
||||
class: 'pf-map-overlay-connection-eol',
|
||||
iconClass: ['far', 'fa-fw', 'fa-clock'],
|
||||
iconClass: ['fas', 'fa-fw', 'fa-hourglass-end'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
@@ -472,7 +473,7 @@ define([
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: '<i class="far fa-fw fa-clock"></i> ' + formatTimeParts(diff),
|
||||
label: '<i class="fas fa-fw fa-hourglass-end"></i> ' + formatTimeParts(diff),
|
||||
id: MapOverlayUtil.config.connectionOverlayEolId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'eol'].join(' '),
|
||||
location: 0.25
|
||||
@@ -542,7 +543,7 @@ define([
|
||||
let percentPerCount = 100 / maxSeconds;
|
||||
|
||||
// update counter
|
||||
let updateChart = function(tempSeconds){
|
||||
let updateChart = tempSeconds => {
|
||||
let pieChart = counterChart.data('easyPieChart');
|
||||
|
||||
if(pieChart !== undefined){
|
||||
@@ -552,7 +553,7 @@ define([
|
||||
};
|
||||
|
||||
// main timer function is called on any counter update
|
||||
let timer = function(mapUpdateCounter){
|
||||
let timer = mapUpdateCounter => {
|
||||
// decrease timer
|
||||
let currentSeconds = counterChart.data('currentSeconds');
|
||||
currentSeconds--;
|
||||
@@ -883,6 +884,8 @@ define([
|
||||
};
|
||||
|
||||
return {
|
||||
showInfoSignatureOverlays: showInfoSignatureOverlays,
|
||||
hideInfoSignatureOverlays: hideInfoSignatureOverlays,
|
||||
updateZoomOverlay: updateZoomOverlay,
|
||||
initMapDebugOverlays: initMapDebugOverlays
|
||||
};
|
||||
|
||||
@@ -9,8 +9,9 @@ define([
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/layout'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout) => {
|
||||
'app/map/layout',
|
||||
'app/map/magnetizing'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout, Magnetizer) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -702,6 +703,9 @@ define([
|
||||
// remove connections do not fire a "connectionDetached" event
|
||||
map.deleteConnectionsForElement(system, {fireEvent: false});
|
||||
|
||||
// unregister from "magnetizer"
|
||||
Magnetizer.removeElement(system.data('mapid'), system[0]);
|
||||
|
||||
// destroy tooltip/popover
|
||||
system.toggleSystemTooltip('destroy', {});
|
||||
system.destroyPopover(true);
|
||||
|
||||
@@ -41,32 +41,6 @@ define([
|
||||
tableCellEllipsis100Class: 'pf-table-cell-100'
|
||||
};
|
||||
|
||||
// map menu options
|
||||
let mapOptions = {
|
||||
mapMagnetizer: {
|
||||
buttonId: Util.config.menuButtonMagnetizerId,
|
||||
description: 'Magnetizer',
|
||||
onEnable: 'initMagnetizer', // jQuery extension function
|
||||
onDisable: 'destroyMagnetizer' // jQuery extension function
|
||||
},
|
||||
mapSnapToGrid : {
|
||||
buttonId: Util.config.menuButtonGridId,
|
||||
description: 'Grid snapping',
|
||||
class: 'mapGridClass'
|
||||
},
|
||||
mapEndpoint : {
|
||||
buttonId: Util.config.menuButtonEndpointId,
|
||||
description: 'Endpoint overlay',
|
||||
onEnable: 'showInfoSignatureOverlays', // jQuery extension function
|
||||
onDisable: 'hideInfoSignatureOverlays' // jQuery extension function
|
||||
},
|
||||
mapCompact : {
|
||||
buttonId: Util.config.menuButtonCompactId,
|
||||
description: 'Compact system layout',
|
||||
class: 'mapCompactClass'
|
||||
}
|
||||
};
|
||||
|
||||
// active jsPlumb instances currently running =====================================================================
|
||||
let activeInstances = {};
|
||||
|
||||
@@ -518,6 +492,7 @@ define([
|
||||
|
||||
if(
|
||||
connection &&
|
||||
connectionData &&
|
||||
connectionData.signatures // signature data is required...
|
||||
){
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
@@ -556,7 +531,7 @@ define([
|
||||
|
||||
if(flattenSigTypeNames.hasOwnProperty(signatureData.typeId)){
|
||||
let label = flattenSigTypeNames[signatureData.typeId];
|
||||
// shorten label, just take the in game name
|
||||
// shorten label, just take the ingame name
|
||||
label = label.substr(0, label.indexOf(' '));
|
||||
signatureTypeData[tmpSystemType].names.push(signatureData.name);
|
||||
signatureTypeData[tmpSystemType].labels.push(label);
|
||||
@@ -574,13 +549,13 @@ define([
|
||||
* -> Coordinates are relative to the Endpoint (not the system!)
|
||||
* -> jsPlumb specific format
|
||||
* @param endpoint
|
||||
* @param label
|
||||
* @param labels
|
||||
* @returns {number[]}
|
||||
*/
|
||||
let getEndpointOverlaySignatureLocation = (endpoint, label) => {
|
||||
let chars = label.length ? label.length : 2;
|
||||
let xLeft = chars === 2 ? -0.5 : chars <= 4 ? -1 : 3;
|
||||
let xRight = chars === 2 ? +1.5 : chars <= 4 ? +2.20 : 3;
|
||||
let getEndpointOverlaySignatureLocation = (endpoint, labels) => {
|
||||
let count = labels.length;
|
||||
let xLeft = count ? count === 1 ? -1.00 : 3 : -0.5;
|
||||
let xRight = count ? count === 1 ? +2.20 : 3 : +1.5;
|
||||
|
||||
switch(endpoint.anchor.getCurrentFace()){
|
||||
case 'top': return [0.5, -0.75];
|
||||
@@ -593,24 +568,25 @@ define([
|
||||
|
||||
/**
|
||||
* get overlay HTML for connection endpoints by Label array
|
||||
* @param label
|
||||
* @param labels
|
||||
* @returns {string}
|
||||
*/
|
||||
let formatEndpointOverlaySignatureLabel = label => {
|
||||
let formatEndpointOverlaySignatureLabel = labels => {
|
||||
// default K162 in label array, or multiple labels
|
||||
let colorClass = 'txt-color-grayLighter';
|
||||
let label = labels.join(', ');
|
||||
|
||||
if(label.length > 0){
|
||||
// check if multiple labels found => conflict
|
||||
if( label.includes(', ') ){
|
||||
colorClass = 'txt-color-orangeLight';
|
||||
}else if( !label.includes('K162') ){
|
||||
colorClass = 'txt-color-yellow';
|
||||
}
|
||||
}else{
|
||||
if(labels.length === 0){
|
||||
// endpoint not connected with a signature
|
||||
label = '<i class="fas fa-question-circle"></i>';
|
||||
colorClass = 'txt-color-red';
|
||||
}else if(
|
||||
labels.length === 1 &&
|
||||
!labels.includes('K162')
|
||||
){
|
||||
colorClass = Init.wormholes[labels[0]].class;
|
||||
}
|
||||
|
||||
return '<span class="txt-color ' + colorClass + '">' + label + '</span>';
|
||||
};
|
||||
|
||||
@@ -639,62 +615,64 @@ define([
|
||||
*/
|
||||
let filterMapByScopes = (map, scopes) => {
|
||||
if(map){
|
||||
let mapElement = $(map.getContainer());
|
||||
let allSystems = mapElement.getSystems();
|
||||
let allConnections = map.getAllConnections();
|
||||
map.batch(() => {
|
||||
let mapElement = $(map.getContainer());
|
||||
let allSystems = mapElement.getSystems();
|
||||
let allConnections = map.getAllConnections();
|
||||
|
||||
if(scopes && scopes.length){
|
||||
// filter connections -------------------------------------------------------------------------------------
|
||||
let visibleSystems = [];
|
||||
let visibleConnections = searchConnectionsByScopeAndType(map, scopes);
|
||||
if(scopes && scopes.length){
|
||||
// filter connections -------------------------------------------------------------------------------------
|
||||
let visibleSystems = [];
|
||||
let visibleConnections = searchConnectionsByScopeAndType(map, scopes);
|
||||
|
||||
for(let connection of allConnections){
|
||||
if(visibleConnections.indexOf(connection) >= 0){
|
||||
setConnectionVisible(connection, true);
|
||||
// source/target system should always be visible -> even if filter scope not matches system type
|
||||
if(visibleSystems.indexOf(connection.endpoints[0].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[0].element);
|
||||
for(let connection of allConnections){
|
||||
if(visibleConnections.indexOf(connection) >= 0){
|
||||
setConnectionVisible(connection, true);
|
||||
// source/target system should always be visible -> even if filter scope not matches system type
|
||||
if(visibleSystems.indexOf(connection.endpoints[0].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[0].element);
|
||||
}
|
||||
if(visibleSystems.indexOf(connection.endpoints[1].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[1].element);
|
||||
}
|
||||
}else{
|
||||
setConnectionVisible(connection, false);
|
||||
}
|
||||
if(visibleSystems.indexOf(connection.endpoints[1].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[1].element);
|
||||
}
|
||||
}else{
|
||||
setConnectionVisible(connection, false);
|
||||
}
|
||||
}
|
||||
|
||||
// filter systems -----------------------------------------------------------------------------------------
|
||||
let visibleTypeIds = [];
|
||||
if(scopes.indexOf('wh') >= 0){
|
||||
visibleTypeIds.push(1);
|
||||
}
|
||||
if(scopes.indexOf('abyssal') >= 0){
|
||||
visibleTypeIds.push(4);
|
||||
}
|
||||
// filter systems -----------------------------------------------------------------------------------------
|
||||
let visibleTypeIds = [];
|
||||
if(scopes.indexOf('wh') >= 0){
|
||||
visibleTypeIds.push(1);
|
||||
}
|
||||
if(scopes.indexOf('abyssal') >= 0){
|
||||
visibleTypeIds.push(4);
|
||||
}
|
||||
|
||||
for(let system of allSystems){
|
||||
if(
|
||||
visibleTypeIds.indexOf($(system).data('typeId')) >= 0 ||
|
||||
visibleSystems.indexOf(system) >= 0
|
||||
){
|
||||
for(let system of allSystems){
|
||||
if(
|
||||
visibleTypeIds.indexOf($(system).data('typeId')) >= 0 ||
|
||||
visibleSystems.indexOf(system) >= 0
|
||||
){
|
||||
setSystemVisible(system, map, true);
|
||||
}else{
|
||||
setSystemVisible(system, map, false);
|
||||
}
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'show');
|
||||
}else{
|
||||
// clear filter
|
||||
for(let system of allSystems){
|
||||
setSystemVisible(system, map, true);
|
||||
}else{
|
||||
setSystemVisible(system, map, false);
|
||||
}
|
||||
}
|
||||
for(let connection of allConnections){
|
||||
setConnectionVisible(connection, true);
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'show');
|
||||
}else{
|
||||
// clear filter
|
||||
for(let system of allSystems){
|
||||
setSystemVisible(system, map, true);
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'hide');
|
||||
}
|
||||
for(let connection of allConnections){
|
||||
setConnectionVisible(connection, true);
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -761,12 +739,11 @@ define([
|
||||
'height': scrollableHeight ? scaledHeight + 'px' : (wrapperHeight) + 'px',
|
||||
});
|
||||
|
||||
|
||||
let mapWrapperElement = mapContainer.closest('.mCustomScrollbar');
|
||||
if(scrollableWidth && scrollableHeight){
|
||||
mapWrapperElement.mCustomScrollbar('update');
|
||||
}else{
|
||||
mapWrapperElement.mCustomScrollbar('scrollTo', '#pf-map-1', {
|
||||
mapWrapperElement.mCustomScrollbar('scrollTo', '#' + mapContainer.attr('id'), {
|
||||
scrollInertia: 0,
|
||||
scrollEasing: 'linear',
|
||||
timeout: 0,
|
||||
@@ -844,40 +821,45 @@ define([
|
||||
* with the addition of respecting active Arrow overlay direction
|
||||
* @param action
|
||||
* @param connection
|
||||
* @param type
|
||||
* @param types
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let changeConnectionType = (action, connection, type, params = {}, doNotRepaint = false) => {
|
||||
// check for active Arrow overlay
|
||||
let overlayArrow, overlayArrowParams;
|
||||
if(
|
||||
type !== 'info_signature' &&
|
||||
connection.hasType('info_signature')
|
||||
){
|
||||
overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
if(overlayArrow){
|
||||
overlayArrowParams = {
|
||||
direction: overlayArrow.direction,
|
||||
foldback: overlayArrow.foldback,
|
||||
};
|
||||
let changeConnectionTypes = (action, connection, types = [], params = [], doNotRepaint = false) => {
|
||||
|
||||
if(connection && types.length){
|
||||
// check for active Arrow overlay
|
||||
let overlayArrow, overlayArrowParams;
|
||||
if(
|
||||
!types.includes('info_signature') &&
|
||||
connection.hasType('info_signature')
|
||||
){
|
||||
overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
if(overlayArrow){
|
||||
overlayArrowParams = {
|
||||
direction: overlayArrow.direction,
|
||||
foldback: overlayArrow.foldback,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the new type
|
||||
connection[action](type, params, doNotRepaint);
|
||||
for(let i = 0; i < types.length; i++){
|
||||
// change the new type
|
||||
connection[action](types[i], typeof params[i] === 'object' ? params[i] : {}, doNotRepaint);
|
||||
}
|
||||
|
||||
// change Arrow overlay data back to initial direction
|
||||
if(
|
||||
overlayArrow &&
|
||||
(
|
||||
overlayArrow.direction !== overlayArrowParams.direction ||
|
||||
overlayArrow.foldback !== overlayArrowParams.foldback
|
||||
)
|
||||
){
|
||||
overlayArrow.updateFrom(overlayArrowParams);
|
||||
if(!doNotRepaint){
|
||||
connection.repaint();
|
||||
// change Arrow overlay data back to initial direction
|
||||
if(
|
||||
overlayArrow &&
|
||||
(
|
||||
overlayArrow.direction !== overlayArrowParams.direction ||
|
||||
overlayArrow.foldback !== overlayArrowParams.foldback
|
||||
)
|
||||
){
|
||||
overlayArrow.updateFrom(overlayArrowParams);
|
||||
if(!doNotRepaint){
|
||||
connection.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -889,8 +871,12 @@ define([
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let addConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('addType', connection, type, params, doNotRepaint);
|
||||
let addConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
addConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
let addConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||||
changeConnectionTypes('addType', connection, types, params, doNotRepaint);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -900,12 +886,16 @@ define([
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let removeConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('removeType', connection, type, params, doNotRepaint);
|
||||
let removeConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
removeConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
let toggleConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('toggleType', connection, type, params, doNotRepaint);
|
||||
let removeConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||||
changeConnectionTypes('removeType', connection, types, params, doNotRepaint);
|
||||
};
|
||||
|
||||
let toggleConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
changeConnectionTypes('toggleType', connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1136,10 +1126,10 @@ define([
|
||||
* @param types
|
||||
* @returns {string[]}
|
||||
*/
|
||||
let getConnectionFakeClassesByTypes = (types) => {
|
||||
let getConnectionFakeClassesByTypes = types => {
|
||||
let connectionClasses = ['pf-fake-connection'];
|
||||
for(let i = 0; i < types.length; i++){
|
||||
connectionClasses.push(getConnectionInfo( types[i], 'cssClass'));
|
||||
connectionClasses.push(getConnectionInfo(types[i], 'cssClass'));
|
||||
}
|
||||
return connectionClasses;
|
||||
};
|
||||
@@ -1147,9 +1137,9 @@ define([
|
||||
/**
|
||||
* get all direct connections between two given systems
|
||||
* @param map
|
||||
* @param {JQuery} systemA
|
||||
* @param {JQuery} systemB
|
||||
* @returns {Array}
|
||||
* @param systemA
|
||||
* @param systemB
|
||||
* @returns {*[]}
|
||||
*/
|
||||
let checkForConnection = (map, systemA, systemB) => {
|
||||
let connections = [];
|
||||
@@ -1224,6 +1214,31 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set/change connection jump mass of a wormhole
|
||||
* @param connection
|
||||
* @param mass
|
||||
*/
|
||||
let setConnectionJumpMassType = (connection, mass) => {
|
||||
let allMassTypes = ['wh_jump_mass_s', 'wh_jump_mass_m', 'wh_jump_mass_l', 'wh_jump_mass_xl'];
|
||||
let addMassType = [];
|
||||
let removeMassTypes = [];
|
||||
|
||||
connection._jsPlumb.instance.batch(() => {
|
||||
if(allMassTypes.includes(mass)){
|
||||
if(connection.hasType(mass)){
|
||||
removeMassTypes = allMassTypes;
|
||||
}else{
|
||||
addMassType = [mass];
|
||||
removeMassTypes = allMassTypes.filter(e => e !== mass);
|
||||
}
|
||||
|
||||
removeConnectionTypes(connection, removeMassTypes);
|
||||
addConnectionTypes(connection, addMassType);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get some scope info for a given info string
|
||||
* @param {string} info
|
||||
@@ -1430,8 +1445,9 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default map Options (
|
||||
* -> HINT: This function triggers Events! Promise is resolved before trigger completed
|
||||
* Set default map options (from right menu)
|
||||
* This function is called only ONCE per map after create!
|
||||
* -> HINT: This function triggers events! Promise is resolved before trigger callback finishes
|
||||
* @param mapElement
|
||||
* @param mapConfig
|
||||
* @returns {Promise<any>}
|
||||
@@ -1464,8 +1480,10 @@ define([
|
||||
|
||||
// init endpoint overlay --------------------------------------------------------------------------
|
||||
mapElement.triggerMenuEvent('MapOption', {
|
||||
option: 'mapEndpoint',
|
||||
toggle: false
|
||||
option: 'mapSignatureOverlays',
|
||||
toggle: false,
|
||||
skipOnEnable: true, // skip callback -> Otherwise it would run 2 times on map create
|
||||
skipOnDisable: true // skip callback -> Otherwise it would run 2 times on map create
|
||||
});
|
||||
|
||||
resolve({
|
||||
@@ -1494,30 +1512,61 @@ define([
|
||||
|
||||
/**
|
||||
* scroll map to default (stored) x/y coordinates
|
||||
* @param mapElement
|
||||
* @param map
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let scrollToDefaultPosition = (mapElement) => {
|
||||
let scrollToDefaultPosition = map => {
|
||||
|
||||
let scrollToDefaultPositionExecutor = (resolve, reject) => {
|
||||
let mapWrapper = mapElement.parents('.' + config.mapWrapperClass);
|
||||
let scrollToDefaultPositionExecutor = resolve => {
|
||||
let payload = {
|
||||
action: 'scrollToDefaultPosition',
|
||||
data: false
|
||||
};
|
||||
|
||||
// auto scroll map to previous stored position
|
||||
// no map scroll on zoomed maps -> scrollbar offset on zoomed maps does not work properly
|
||||
// -> implementation would be difficult...
|
||||
if(map.getZoom() === 1){
|
||||
let mapElement = $(map.getContainer());
|
||||
let promiseStore = getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(data => {
|
||||
if(data && data.scrollOffset){
|
||||
let mapWrapper = mapElement.parents('.' + config.mapWrapperClass);
|
||||
Scrollbar.scrollToPosition(mapWrapper, [data.scrollOffset.y, data.scrollOffset.x]);
|
||||
}
|
||||
|
||||
resolve(payload);
|
||||
});
|
||||
}else{
|
||||
resolve(payload);
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(scrollToDefaultPositionExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* zoom map to default (stored) scale()
|
||||
* @param map
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let zoomToDefaultScale = map => {
|
||||
|
||||
let zoomToDefaultScaleExecutor = resolve => {
|
||||
let mapElement = $(map.getContainer());
|
||||
let promiseStore = getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(data => {
|
||||
// This code runs once the value has been loaded from offline storage
|
||||
if(data && data.scrollOffset){
|
||||
Scrollbar.scrollToPosition(mapWrapper, [data.scrollOffset.y, data.scrollOffset.x]);
|
||||
if(data && data.mapZoom){
|
||||
setZoom(map, data.mapZoom);
|
||||
}
|
||||
|
||||
resolve({
|
||||
action: 'scrollToDefaultPosition',
|
||||
action: 'zoomToDefaultScale',
|
||||
data: false
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(scrollToDefaultPositionExecutor);
|
||||
return new Promise(zoomToDefaultScaleExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1825,13 +1874,12 @@ define([
|
||||
|
||||
let title = tooltipData.name;
|
||||
|
||||
if(tooltipData.size){
|
||||
title += ' <kbd>' + tooltipData.size.label + '</kbd>';
|
||||
}
|
||||
|
||||
if(tooltipData.security){
|
||||
// K162 has no security
|
||||
|
||||
if(!tooltipData.class){
|
||||
tooltipData.class = Util.getSecurityClassForSystem(tooltipData.security);
|
||||
}
|
||||
|
||||
title += '<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>';
|
||||
}
|
||||
|
||||
@@ -1961,7 +2009,6 @@ define([
|
||||
|
||||
return {
|
||||
config: config,
|
||||
mapOptions: mapOptions,
|
||||
setMapInstance: setMapInstance,
|
||||
getMapInstance: getMapInstance,
|
||||
existsMapInstance: existsMapInstance,
|
||||
@@ -1996,6 +2043,7 @@ define([
|
||||
checkForConnection: checkForConnection,
|
||||
getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope,
|
||||
setConnectionWHStatus: setConnectionWHStatus,
|
||||
setConnectionJumpMassType: setConnectionJumpMassType,
|
||||
getScopeInfoForConnection: getScopeInfoForConnection,
|
||||
getDataByConnections: getDataByConnections,
|
||||
deleteConnections: deleteConnections,
|
||||
@@ -2016,6 +2064,7 @@ define([
|
||||
setMapDefaultOptions: setMapDefaultOptions,
|
||||
getSystemPosition: getSystemPosition,
|
||||
scrollToDefaultPosition: scrollToDefaultPosition,
|
||||
zoomToDefaultScale: zoomToDefaultScale,
|
||||
getSystemId: getSystemId,
|
||||
checkRight: checkRight,
|
||||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||||
|
||||
@@ -121,6 +121,25 @@ define([
|
||||
*/
|
||||
let initData = () => {
|
||||
|
||||
/**
|
||||
* add wormhole size data for each wormhole
|
||||
* @param wormholes
|
||||
* @returns {*}
|
||||
*/
|
||||
let addWormholeSizeData = wormholes => {
|
||||
for(let [wormholeName, wormholeData] of Object.entries(wormholes)){
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
|
||||
for(let [sizeName, sizeData] of Object.entries(Init.wormholeSizes)){
|
||||
if(wormholeData.massIndividual >= sizeData.jumpMassMin){
|
||||
wormholeData.size = sizeData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return wormholes;
|
||||
};
|
||||
|
||||
let initDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.initData).done(response => {
|
||||
if( response.error.length > 0 ){
|
||||
@@ -139,7 +158,7 @@ define([
|
||||
Init.connectionScopes = response.connectionScopes;
|
||||
Init.systemStatus = response.systemStatus;
|
||||
Init.systemType = response.systemType;
|
||||
Init.wormholes = response.wormholes;
|
||||
Init.wormholes = addWormholeSizeData(response.wormholes);
|
||||
Init.characterStatus = response.characterStatus;
|
||||
Init.routes = response.routes;
|
||||
Init.url = response.url;
|
||||
|
||||
@@ -220,17 +220,7 @@ define([
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Effect info'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-crosshairs fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSystemEffectInfo');
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Jump info'
|
||||
html: ' Wormhole data'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-space-shuttle fa-fw'
|
||||
@@ -238,6 +228,16 @@ define([
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowJumpInfo');
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Wormhole effects'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-crosshairs fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSystemEffectInfo');
|
||||
}),
|
||||
getMenuHeadline('Settings'),
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
@@ -379,7 +379,7 @@ define([
|
||||
})
|
||||
).on('click', function(){
|
||||
Util.getMapModule().getActiveMap().triggerMenuEvent('MapOption', {
|
||||
option: 'mapEndpoint',
|
||||
option: 'mapSignatureOverlays',
|
||||
toggle: true
|
||||
});
|
||||
}),
|
||||
|
||||
@@ -26,13 +26,6 @@ define([
|
||||
let data = {
|
||||
config: config,
|
||||
wormholes: Object.keys(Init.wormholes).map(function(k){ return Init.wormholes[k]; }), // convert Json to array
|
||||
securityClass: function(){
|
||||
return function(value, render){
|
||||
return this.Util.getSecurityClassForSystem( render(value) );
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
}),
|
||||
massValue: function(){
|
||||
return function(value, render){
|
||||
let mass = render(value);
|
||||
|
||||
@@ -382,9 +382,7 @@ define([
|
||||
let statics = [];
|
||||
for(let wormholeName of cellData){
|
||||
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
let security = wormholeData.security;
|
||||
let secClass = Util.getSecurityClassForSystem(security);
|
||||
statics.push('<span class="' + secClass + '">' + security + '</span>');
|
||||
statics.push('<span class="' + wormholeData.class + '">' + wormholeData.security + '</span>');
|
||||
}
|
||||
return statics.join(' ');
|
||||
}
|
||||
@@ -596,7 +594,7 @@ define([
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
let connectionClasses = MapUtil.getConnectionFakeClassesByTypes(cellData);
|
||||
connectionClasses = connectionClasses.join(' ');
|
||||
return '<div class="pf-fake-connection ' + connectionClasses + '"></div>';
|
||||
return '<div class="' + connectionClasses + '"></div>';
|
||||
}
|
||||
}
|
||||
},{
|
||||
|
||||
@@ -57,7 +57,7 @@ define([
|
||||
|
||||
for(let [areaId, areaData] of Object.entries(effectData)){
|
||||
let systemType = 'C' + areaId;
|
||||
let securityClass = Util.getSecurityClassForSystem( systemType );
|
||||
let securityClass = Util.getSecurityClassForSystem(systemType);
|
||||
|
||||
if(areaId === '1'){
|
||||
rows.push( $('<tr>') );
|
||||
|
||||
@@ -166,7 +166,7 @@ define([
|
||||
if(type.includes('wh_critical')){
|
||||
styleClass.push('pf-wh-critical');
|
||||
}
|
||||
if(type.includes('frigate')){
|
||||
if(type.includes('wh_jump_mass_s')){
|
||||
styleClass.push('pf-wh-frig');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,22 +306,22 @@ define([
|
||||
let connection = $().getConnectionById(data.mapId, data.connectionId);
|
||||
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sourceLabel = signatureTypeNames.source.labels;
|
||||
let targetLabel = signatureTypeNames.target.labels;
|
||||
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabel.join(', ')));
|
||||
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabel.join(', ')));
|
||||
let sourceLabels = signatureTypeNames.source.labels;
|
||||
let targetLabels = signatureTypeNames.target.labels;
|
||||
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabels));
|
||||
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabels));
|
||||
|
||||
// remove K162
|
||||
sourceLabel = sourceLabel.diff(['K162']);
|
||||
targetLabel = targetLabel.diff(['K162']);
|
||||
sourceLabels = sourceLabels.diff(['K162']);
|
||||
targetLabels = targetLabels.diff(['K162']);
|
||||
|
||||
// get static wormhole data by endpoint Labels
|
||||
let wormholeName = '';
|
||||
let wormholeData = null;
|
||||
if(sourceLabel.length === 1 && targetLabel.length === 0){
|
||||
wormholeName = sourceLabel[0];
|
||||
}else if(sourceLabel.length === 0 && targetLabel.length === 1){
|
||||
wormholeName = targetLabel[0];
|
||||
if(sourceLabels.length === 1 && targetLabels.length === 0){
|
||||
wormholeName = sourceLabels[0];
|
||||
}else if(sourceLabels.length === 0 && targetLabels.length === 1){
|
||||
wormholeName = targetLabels[0];
|
||||
}
|
||||
|
||||
if(
|
||||
@@ -329,7 +329,6 @@ define([
|
||||
Init.wormholes.hasOwnProperty(wormholeName)
|
||||
){
|
||||
wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
|
||||
// init wormhole tooltip ----------------------------------------------
|
||||
let massTotalTooltipCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalTooltipClass);
|
||||
|
||||
@@ -143,7 +143,6 @@ define([
|
||||
){
|
||||
for(let wormholeName of systemData.statics){
|
||||
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
staticsData.push(wormholeData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +970,16 @@ define([
|
||||
return this.filter(function(i){return a.indexOf(i) < 0;});
|
||||
};
|
||||
|
||||
/**
|
||||
* compares two arrays if all elements in a are also in b
|
||||
* element order is ignored
|
||||
* @param a
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Array.prototype.equalValues = function(a){
|
||||
return this.diff(a).concat(a.diff(this)).length === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* sort array of objects by property name
|
||||
* @param p
|
||||
|
||||
@@ -1,350 +0,0 @@
|
||||
;(function() {
|
||||
|
||||
var root = this;
|
||||
var Farahey;
|
||||
if (typeof exports !== 'undefined') {
|
||||
Farahey = exports;
|
||||
} else {
|
||||
Farahey = root.Farahey = {};
|
||||
}
|
||||
|
||||
var findInsertionPoint = function(sortedArr, val, comparator) {
|
||||
var low = 0, high = sortedArr.length;
|
||||
var mid = -1, c = 0;
|
||||
while(low < high) {
|
||||
mid = parseInt((low + high)/2);
|
||||
c = comparator(sortedArr[mid], val);
|
||||
if(c < 0) {
|
||||
low = mid + 1;
|
||||
}else if(c > 0) {
|
||||
high = mid;
|
||||
}else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
},
|
||||
geomSupport = typeof jsPlumbGeom !== "undefined" ? jsPlumbGeom : Biltong,
|
||||
insertSorted = function(array, value, comparator) {
|
||||
var ip = findInsertionPoint(array, value, comparator);
|
||||
array.splice(ip, 0, value);
|
||||
},
|
||||
distanceFromOriginComparator = function(r1, r2, origin) {
|
||||
var d1 = geomSupport.lineLength(origin, [ r1.x + (r1.w / 2), r1.y + (r1.h / 2)]),
|
||||
d2 = geomSupport.lineLength(origin, [ r2.x + (r2.w / 2), r2.y + (r2.h / 2)]);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
},
|
||||
EntryComparator = function(origin, getSize) {
|
||||
var _origin = origin,
|
||||
_cache = {},
|
||||
_get = function(entry) {
|
||||
if (!_cache[entry[1]]) {
|
||||
var s = getSize(entry[2]);
|
||||
_cache[entry[1]] = {
|
||||
l:entry[0][0],
|
||||
t:entry[0][1],
|
||||
w:s[0],
|
||||
h:s[1],
|
||||
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
|
||||
};
|
||||
}
|
||||
return _cache[entry[1]];
|
||||
}
|
||||
this.setOrigin = function(o) {
|
||||
_origin = o;
|
||||
_cache = {};
|
||||
};
|
||||
this.compare = function(e1, e2) {
|
||||
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
|
||||
d2 = geomSupport.lineLength(_origin, _get(e2).center);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
|
||||
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
|
||||
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
|
||||
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
|
||||
_genAdj = function(r1, r2, m, b, s) {
|
||||
if (isNaN(m)) m = 0;
|
||||
var y = r2.y + r2.h,
|
||||
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
|
||||
theta = Math.atan(m);
|
||||
|
||||
if (_isOnEdge(r2, "x", "w", x)) {
|
||||
var rise = _adj[s][1](r1, r2),
|
||||
hyp = rise / Math.sin(theta),
|
||||
run = hyp * Math.cos(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
else {
|
||||
var run = _adj[s][0](r1, r2),
|
||||
hyp = run / Math.cos(theta),
|
||||
rise = hyp * Math.sin(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
},
|
||||
/*
|
||||
* Calculates how far to move r2 from r1 so that it no longer overlaps.
|
||||
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
|
||||
* otherwise we want it to move along a vector joining the two rectangle centers.
|
||||
*/
|
||||
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
|
||||
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
|
||||
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
|
||||
m = geomSupport.gradient(c1, c2),
|
||||
s = geomSupport.quadrant(c1, c2),
|
||||
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
|
||||
|
||||
return _genAdj(r1, r2, m, b, s);
|
||||
},
|
||||
// calculate a padded rectangle for the given element with offset & size, and desired padding.
|
||||
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
|
||||
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
|
||||
},
|
||||
_magnetize = function(positionArray, positions, sizes, padding,
|
||||
constrain, origin, filter,
|
||||
updateOnStep, stepInterval, stepCallback)
|
||||
{
|
||||
origin = origin || [0,0];
|
||||
stepCallback = stepCallback || function() { };
|
||||
|
||||
var focus = _paddedRectangle(origin, [1,1], padding),
|
||||
iterations = 100, iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
|
||||
_movedElements = {},
|
||||
_move = function(id, o, x, y) {
|
||||
_movedElements[id] = true;
|
||||
o[0] += x;
|
||||
o[1] += y;
|
||||
},
|
||||
step = function() {
|
||||
for (var i = 0; i < positionArray.length; i++) {
|
||||
var o1 = positions[positionArray[i][1]],
|
||||
oid = positionArray[i][1],
|
||||
a1 = positionArray[i][2], // angle to node from magnet origin
|
||||
s1 = sizes[positionArray[i][1]],
|
||||
// create a rectangle for first element: this encompasses the element and padding on each
|
||||
//side
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
|
||||
if (filter(positionArray[i][1]) && geomSupport.intersects(focus, r1)) {
|
||||
adjustBy = _calculateSpacingAdjustment(focus, r1);
|
||||
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
|
||||
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
|
||||
// now move others to account for this one, if necessary.
|
||||
// reset rectangle for node
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
for (var j = 0; j < positionArray.length; j++) {
|
||||
if (i != j) {
|
||||
var o2 = positions[positionArray[j][1]],
|
||||
a2 = positionArray[j][2], // angle to node from magnet origin
|
||||
s2 = sizes[positionArray[j][1]],
|
||||
// create a rectangle for the second element, again by putting padding of the desired
|
||||
// amount around the bounds of the element.
|
||||
r2 = _paddedRectangle(o2, s2, padding);
|
||||
|
||||
// if the two rectangles intersect then figure out how much to move the second one by.
|
||||
if (geomSupport.intersects(r1, r2)) {
|
||||
// TODO in 0.3, instead of moving neither, the other node should move.
|
||||
if (filter(positionArray[j][1])) {
|
||||
uncleanRun = true;
|
||||
adjustBy = _calculateSpacingAdjustment(r1, r2),
|
||||
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
|
||||
|
||||
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateOnStep)
|
||||
stepCallback();
|
||||
|
||||
if (uncleanRun && iteration < iterations) {
|
||||
uncleanRun = false;
|
||||
iteration++;
|
||||
if (updateOnStep) {
|
||||
window.setTimeout(step, stepInterval);
|
||||
}
|
||||
else
|
||||
step();
|
||||
}
|
||||
};
|
||||
|
||||
step();
|
||||
return _movedElements;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @name Magnetizer
|
||||
* @classdesc Applies repulsive magnetism to a set of elements relative to a given point, with a specified
|
||||
* amount of padding around the point.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Magnetizer#constructor
|
||||
* @function
|
||||
* @param {Selector|Element} [container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} getPosition A function that takes an element id and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} setPosition A function that takes an element id and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} getSize A function that takes an element id and returns its size, in pixels.
|
||||
* @param {Integer[]} [padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Integer[]} [origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} elements List of elements on which to operate.
|
||||
* @param {Boolean} [executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
root.Magnetizer = function(params) {
|
||||
var getPosition = params.getPosition,
|
||||
getSize = params.getSize,
|
||||
getId = params.getId,
|
||||
setPosition = params.setPosition,
|
||||
padding = params.padding || [20, 20],
|
||||
// expects a { left:.., top:... } object. returns how far it can actually go.
|
||||
constrain = params.constrain || function(id, current, delta) { return delta; },
|
||||
positionArray = [],
|
||||
positions = {},
|
||||
sizes = {},
|
||||
elements = params.elements || [],
|
||||
origin = params.origin || [0,0],
|
||||
executeNow = params.executeNow,
|
||||
minx, miny, maxx, maxy,
|
||||
getOrigin = this.getOrigin = function() { return origin; },
|
||||
filter = params.filter || function(_) { return true; },
|
||||
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
|
||||
comparator = new EntryComparator(origin, getSize),
|
||||
updateOnStep = params.updateOnStep,
|
||||
stepInterval = params.stepInterval || 350,
|
||||
originDebugMarker,
|
||||
debug = params.debug,
|
||||
createOriginDebugger = function() {
|
||||
var d = document.createElement("div");
|
||||
d.style.position = "absolute";
|
||||
d.style.width = "10px";
|
||||
d.style.height = "10px";
|
||||
d.style.backgroundColor = "red";
|
||||
document.body.appendChild(d);
|
||||
originDebugMarker = d;
|
||||
},
|
||||
_addToPositionArray = function(p) {
|
||||
if (!orderByDistanceFromOrigin || positionArray.length == 0)
|
||||
positionArray.push(p);
|
||||
else {
|
||||
insertSorted(positionArray, p, comparator.compare);
|
||||
}
|
||||
},
|
||||
_updatePositions = function() {
|
||||
comparator.setOrigin(origin);
|
||||
positionArray = []; positions = {}; sizes = {};
|
||||
minx = miny = Infinity;
|
||||
maxx = maxy = -Infinity;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var p = getPosition(elements[i]),
|
||||
s = getSize(elements[i]),
|
||||
id = getId(elements[i]);
|
||||
|
||||
positions[id] = [p.left, p.top];
|
||||
_addToPositionArray([ [p.left, p.top], id, elements[i]]);
|
||||
sizes[id] = s;
|
||||
minx = Math.min(minx, p.left);
|
||||
miny = Math.min(miny, p.top);
|
||||
maxx = Math.max(maxx, p.left + s[0]);
|
||||
maxy = Math.max(maxy, p.top + s[1]);
|
||||
}
|
||||
},
|
||||
_run = function() {
|
||||
if (elements.length > 1) {
|
||||
var _movedElements = _magnetize(positionArray, positions, sizes, padding, constrain, origin, filter, updateOnStep, stepInterval, _positionElements);
|
||||
_positionElements(_movedElements);
|
||||
}
|
||||
},
|
||||
_positionElements = function(_movedElements) {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var id = getId(elements[i]);
|
||||
if (_movedElements[id])
|
||||
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
|
||||
}
|
||||
},
|
||||
setOrigin = function(o) {
|
||||
if (o != null) {
|
||||
origin = o;
|
||||
comparator.setOrigin(o);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#execute
|
||||
* @function
|
||||
* @desc Runs the magnetize routine.
|
||||
* @param {Integer[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
|
||||
*/
|
||||
this.execute = function(o) {
|
||||
setOrigin(o);
|
||||
_updatePositions();
|
||||
_run();
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#executeAtCenter
|
||||
* @function
|
||||
* @desc Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
|
||||
*/
|
||||
this.executeAtCenter = function() {
|
||||
_updatePositions();
|
||||
setOrigin([
|
||||
(minx + maxx) / 2,
|
||||
(miny + maxy) / 2
|
||||
]);
|
||||
_run();
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#executeAtEvent
|
||||
* @function
|
||||
* @desc Runs the magnetize routine using the location of the given event as the origin. To use this
|
||||
* method you need to have provided a `container`, and a `getContainerPosition` function to the
|
||||
* constructor.
|
||||
* @param {Event} e Event to get origin location from.
|
||||
*/
|
||||
this.executeAtEvent = function(e) {
|
||||
var c = params.container,
|
||||
o = params.getContainerPosition(c),
|
||||
x = e.pageX - o.left + c[0].scrollLeft,
|
||||
y = e.pageY - o.top + c[0].scrollTop;
|
||||
|
||||
if (debug) {
|
||||
originDebugMarker.style.left = e.pageX + "px";
|
||||
originDebugMarker.style.top = e.pageY + "px";
|
||||
}
|
||||
|
||||
this.execute([x,y]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetize#setElements
|
||||
* @function
|
||||
* @desc Sets the current list of elements.
|
||||
* @param {Object[]} _els List of elements, in whatever format the magnetizer is setup to use.
|
||||
*/
|
||||
this.setElements = function(_els) {
|
||||
elements = _els;
|
||||
};
|
||||
|
||||
|
||||
if (debug)
|
||||
createOriginDebugger();
|
||||
|
||||
if (executeNow) this.execute();
|
||||
|
||||
};
|
||||
}).call(this);
|
||||
|
||||
518
js/lib/farahey.js
Normal file
518
js/lib/farahey.js
Normal file
@@ -0,0 +1,518 @@
|
||||
;(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
var root = this;
|
||||
var Farahey = root.Farahey = {};
|
||||
if (typeof exports !== 'undefined') {
|
||||
exports.Farahey = Farahey;
|
||||
}
|
||||
|
||||
var findInsertionPoint = function(sortedArr, val, comparator) {
|
||||
var low = 0, high = sortedArr.length;
|
||||
var mid = -1, c = 0;
|
||||
while(low < high) {
|
||||
mid = parseInt((low + high)/2);
|
||||
c = comparator(sortedArr[mid], val);
|
||||
if(c < 0) {
|
||||
low = mid + 1;
|
||||
}else if(c > 0) {
|
||||
high = mid;
|
||||
}else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
},
|
||||
geomSupport = root.Biltong,
|
||||
insertSorted = function(array, value, comparator) {
|
||||
var ip = findInsertionPoint(array, value, comparator);
|
||||
array.splice(ip, 0, value);
|
||||
},
|
||||
EntryComparator = function(origin, getSize) {
|
||||
var _origin = origin,
|
||||
_cache = {},
|
||||
_get = function(entry) {
|
||||
if (!_cache[entry[1]]) {
|
||||
var s = getSize(entry[2]);
|
||||
_cache[entry[1]] = {
|
||||
l:entry[0][0],
|
||||
t:entry[0][1],
|
||||
w:s[0],
|
||||
h:s[1],
|
||||
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
|
||||
};
|
||||
}
|
||||
return _cache[entry[1]];
|
||||
};
|
||||
|
||||
this.setOrigin = function(o) {
|
||||
_origin = o;
|
||||
_cache = {};
|
||||
};
|
||||
this.compare = function(e1, e2) {
|
||||
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
|
||||
d2 = geomSupport.lineLength(_origin, _get(e2).center);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
|
||||
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
|
||||
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
|
||||
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
|
||||
_genAdj = function(r1, r2, m, b, s) {
|
||||
if (isNaN(m)) m = 0;
|
||||
var y = r2.y + r2.h,
|
||||
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
|
||||
theta = Math.atan(m),
|
||||
rise, hyp, run;
|
||||
|
||||
if (_isOnEdge(r2, "x", "w", x)) {
|
||||
rise = _adj[s][1](r1, r2);
|
||||
hyp = rise / Math.sin(theta);
|
||||
run = hyp * Math.cos(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
else {
|
||||
run = _adj[s][0](r1, r2);
|
||||
hyp = run / Math.cos(theta);
|
||||
rise = hyp * Math.sin(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
},
|
||||
/*
|
||||
* Calculates how far to move r2 from r1 so that it no longer overlaps.
|
||||
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
|
||||
* otherwise we want it to move along a vector joining the two rectangle centers.
|
||||
*/
|
||||
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
|
||||
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
|
||||
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
|
||||
m = geomSupport.gradient(c1, c2),
|
||||
s = geomSupport.quadrant(c1, c2),
|
||||
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
|
||||
|
||||
return _genAdj(r1, r2, m, b, s);
|
||||
},
|
||||
// calculate a padded rectangle for the given element with offset & size, and desired padding.
|
||||
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
|
||||
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
|
||||
},
|
||||
_magnetize = function(positionArray, positions, sizes, padding,
|
||||
constrain, origin, filter,
|
||||
updateOnStep, stepInterval, stepCallback, iterations,
|
||||
exclude, excludeFocus)
|
||||
{
|
||||
origin = origin || [0,0];
|
||||
stepCallback = stepCallback || function() { };
|
||||
iterations = iterations || 2;
|
||||
|
||||
var focus = _paddedRectangle(origin, [1,1], padding),
|
||||
iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
|
||||
_movedElements = {},
|
||||
_move = function(id, o, x, y) {
|
||||
_movedElements[id] = true;
|
||||
o[0] += x;
|
||||
o[1] += y;
|
||||
},
|
||||
step = function() {
|
||||
for (var i = 0; i < positionArray.length; i++) {
|
||||
|
||||
if (exclude(positionArray[i][1], positionArray[i][2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var o1 = positions[positionArray[i][1]],
|
||||
oid = positionArray[i][1],
|
||||
a1 = positionArray[i][2], // angle to node from magnet origin
|
||||
s1 = sizes[positionArray[i][1]],
|
||||
// create a rectangle for first element: this encompasses the element and padding on each
|
||||
//side
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
|
||||
if (!excludeFocus && filter(positionArray[i][1], positionArray[i][2]) && geomSupport.intersects(focus, r1)) {
|
||||
adjustBy = _calculateSpacingAdjustment(focus, r1);
|
||||
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
|
||||
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
|
||||
// now move others to account for this one, if necessary.
|
||||
// reset rectangle for node
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
for (var j = 0; j < positionArray.length; j++) {
|
||||
if (i != j) {
|
||||
|
||||
if (exclude(positionArray[j][1], positionArray[j][2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter(positionArray[j][1], positionArray[j][2])) {
|
||||
var o2 = positions[positionArray[j][1]],
|
||||
s2 = sizes[positionArray[j][1]],
|
||||
// create a rectangle for the second element, again by putting padding of the desired
|
||||
// amount around the bounds of the element.
|
||||
r2 = _paddedRectangle(o2, s2, padding);
|
||||
|
||||
// if the two rectangles intersect then figure out how much to move the second one by.
|
||||
if (geomSupport.intersects(r1, r2)) {
|
||||
// TODO (?), instead of moving neither, the other node should move.
|
||||
uncleanRun = true;
|
||||
adjustBy = _calculateSpacingAdjustment(r1, r2);
|
||||
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
|
||||
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateOnStep)
|
||||
stepCallback();
|
||||
|
||||
if (uncleanRun && iteration < iterations) {
|
||||
uncleanRun = false;
|
||||
iteration++;
|
||||
if (updateOnStep) {
|
||||
window.setTimeout(step, stepInterval);
|
||||
}
|
||||
else
|
||||
step();
|
||||
}
|
||||
};
|
||||
|
||||
step();
|
||||
return _movedElements;
|
||||
};
|
||||
|
||||
var _convertElements = function(l) {
|
||||
if (l == null) return null;
|
||||
else if (Object.prototype.toString.call(l) === "[object Array]") {
|
||||
var a = [];
|
||||
a.push.apply(a, l);
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
var o = [];
|
||||
for (var i in l) o.push(l[i]);
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies repulsive magnetism to a set of elements relative to a given point, with a specified
|
||||
* amount of padding around the point.
|
||||
* @class FaraheyInstance
|
||||
* @constructor
|
||||
* @param {Object} params Constructor parameters.
|
||||
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
|
||||
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
|
||||
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
var FaraheyInstance = function(params) {
|
||||
var getPosition = params.getPosition,
|
||||
getSize = params.getSize,
|
||||
getId = params.getId,
|
||||
setPosition = params.setPosition,
|
||||
padding = params.padding || [20, 20],
|
||||
// expects a { left:.., top:... } object. returns how far it can actually go.
|
||||
constrain = params.constrain || function(id, current, delta) { return delta; },
|
||||
positionArray = [],
|
||||
positions = {},
|
||||
sizes = {},
|
||||
elements = _convertElements(params.elements || []),
|
||||
origin = params.origin || [0,0],
|
||||
executeNow = params.executeNow,
|
||||
//minx, miny, maxx, maxy,
|
||||
getOrigin = this.getOrigin = function() { return origin; },
|
||||
filter = params.filter || function(_) { return true; },
|
||||
exclude = params.exclude || function(_) { return false;},
|
||||
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
|
||||
comparator = new EntryComparator(origin, getSize),
|
||||
updateOnStep = params.updateOnStep,
|
||||
stepInterval = params.stepInterval || 350,
|
||||
originDebugMarker,
|
||||
debug = params.debug,
|
||||
createOriginDebugger = function() {
|
||||
var d = document.createElement("div");
|
||||
d.style.position = "absolute";
|
||||
d.style.width = "10px";
|
||||
d.style.height = "10px";
|
||||
d.style.backgroundColor = "red";
|
||||
document.body.appendChild(d);
|
||||
originDebugMarker = d;
|
||||
},
|
||||
_addToPositionArray = function(p) {
|
||||
if (!orderByDistanceFromOrigin || positionArray.length == 0)
|
||||
positionArray.push(p);
|
||||
else {
|
||||
insertSorted(positionArray, p, comparator.compare);
|
||||
}
|
||||
},
|
||||
_computeExtents = function(els) {
|
||||
var minx, miny, maxx, maxy;
|
||||
minx = miny = Infinity;
|
||||
maxx = maxy = -Infinity;
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
var p = getPosition(els[i]),
|
||||
s = getSize(els[i]),
|
||||
id = getId(els[i]);
|
||||
|
||||
positions[id] = [p.left, p.top];
|
||||
_addToPositionArray([ [p.left, p.top], id, els[i]]);
|
||||
sizes[id] = s;
|
||||
minx = Math.min(minx, p.left);
|
||||
miny = Math.min(miny, p.top);
|
||||
maxx = Math.max(maxx, p.left + s[0]);
|
||||
maxy = Math.max(maxy, p.top + s[1]);
|
||||
}
|
||||
|
||||
return [ minx, maxx, miny, maxy ];
|
||||
|
||||
},
|
||||
_updatePositions = function() {
|
||||
comparator.setOrigin(origin);
|
||||
positionArray = []; positions = {}; sizes = {};
|
||||
return _computeExtents(elements);
|
||||
},
|
||||
_run = function(options) {
|
||||
if (elements.length > 1) {
|
||||
options = options || {};
|
||||
var f = options.filter || filter;
|
||||
var p = options.padding || padding;
|
||||
var i = options.iterations;
|
||||
var e = options.exclude || exclude;
|
||||
var ef = options.excludeFocus;
|
||||
var _movedElements = _magnetize(positionArray, positions, sizes, p, constrain, origin, f, updateOnStep, stepInterval, _positionElements, i, e, ef);
|
||||
_positionElements(_movedElements);
|
||||
}
|
||||
},
|
||||
_positionElements = function(_movedElements) {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var id = getId(elements[i]);
|
||||
if (_movedElements[id])
|
||||
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
|
||||
}
|
||||
},
|
||||
setOrigin = function(o) {
|
||||
if (o != null) {
|
||||
origin = o;
|
||||
comparator.setOrigin(o);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the magnetize routine.
|
||||
* @method execute
|
||||
* @param {Number[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.execute = function(o, options) {
|
||||
setOrigin(o);
|
||||
_updatePositions();
|
||||
_run(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
|
||||
* @method executeAtCenter
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.executeAtCenter = function(options) {
|
||||
var extents = _updatePositions();
|
||||
setOrigin([
|
||||
(extents[0] + extents[1]) / 2,
|
||||
(extents[2] + extents[3]) / 2
|
||||
]);
|
||||
_run(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the magnetize routine using the location of the given event as the origin. To use this
|
||||
* method you need to have provided a `container`, and a `getContainerPosition` function to the
|
||||
* constructor.
|
||||
* @method executeAtEvent
|
||||
* @param {Event} e Event to get origin location from.
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.executeAtEvent = function(e, options) {
|
||||
var c = params.container,
|
||||
o = params.getContainerPosition(c),
|
||||
x = e.pageX - o.left + c.scrollLeft,
|
||||
y = e.pageY - o.top + c.scrollTop;
|
||||
|
||||
if (debug) {
|
||||
originDebugMarker.style.left = e.pageX + "px";
|
||||
originDebugMarker.style.top = e.pageY + "px";
|
||||
}
|
||||
|
||||
this.execute([x,y], options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current set of elements on which to operate.
|
||||
* @method setElements
|
||||
* @param {Object[]|Object} _els List, or object hash, of elements, in whatever format the Magnetizer is setup to use. If you supply an object hash then a list is generated from the hash's values (the keys are ignored).
|
||||
*/
|
||||
this.setElements = function(_els) {
|
||||
elements = _convertElements(_els);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given element to the set of elements on which to operate.
|
||||
* @method addElement
|
||||
* @param el {Object} Element to add.
|
||||
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
|
||||
* for a much faster call when there are lots of elements, just use it with care.
|
||||
*/
|
||||
this.addElement = function(el, doNotTestForDuplicates) {
|
||||
if (el != null && (doNotTestForDuplicates || elements.indexOf(el) === -1)) {
|
||||
elements.push(el);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given elements to the set of elements on which to operate.
|
||||
* @method addElements
|
||||
* @param els {Object[]} Elements to add.
|
||||
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
|
||||
* for a much faster call when there are lots of elements, just use it with care.
|
||||
*/
|
||||
this.addElements = function(els, doNotTestForDuplicates) {
|
||||
if (doNotTestForDuplicates) {
|
||||
Array.prototype.push.apply(elements, els);
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
this.addElement(els[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the list of elements currently being managed.
|
||||
* @method getElements
|
||||
*/
|
||||
this.getElements = function() {
|
||||
return elements;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given element from the set of elements on which to operate.
|
||||
* @method removeElement
|
||||
* @param el {Object} Element to remove.
|
||||
*/
|
||||
this.removeElement = function(el) {
|
||||
var idx = -1;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i] == el) {
|
||||
idx = i; break;
|
||||
}
|
||||
}
|
||||
if (idx != -1) elements.splice(idx, 1);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the padding to insert between magnetized elements.
|
||||
* @method setPadding
|
||||
* @param {Number[]} p Array of padding for each axis.
|
||||
*/
|
||||
this.setPadding = function(p) {
|
||||
padding = p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the function used to constrain the movement of some element that the magnetizer wishes to relocate.
|
||||
* The function is given an element ID and an array of [x,y] values, where each value indicates the proposed amount
|
||||
* of movement in the given axis. The function is expected to return an array of [x,y] that indicates the allowed
|
||||
* amount of movement in each axis.
|
||||
* @method setConstrain
|
||||
* @param {Function} c
|
||||
*/
|
||||
this.setConstrain = function(c) {
|
||||
constrain = c;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the function used to determine whether or not a given element should be considered during the magnetization process.
|
||||
* @method setFilter
|
||||
* @param {Function} f Filter function to use. Takes an element ID and returns whether or not that element can be moved.
|
||||
*/
|
||||
this.setFilter = function(f) {
|
||||
filter = f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the Farahey instance. Use this to avoid memory leaks.
|
||||
* @method reset
|
||||
*/
|
||||
this.reset = function() {
|
||||
elements.length = 0;
|
||||
};
|
||||
|
||||
if (debug)
|
||||
createOriginDebugger();
|
||||
|
||||
if (executeNow) this.execute();
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a new FaraheyInstance
|
||||
* @method
|
||||
* @param {Object} params Method parameters.
|
||||
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
|
||||
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
|
||||
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
Farahey.getInstance = function(params) {
|
||||
return new FaraheyInstance(params);
|
||||
};
|
||||
|
||||
}).call(typeof window !== 'undefined' ? window : this);
|
||||
|
||||
@@ -67,8 +67,12 @@ $.fn.dragToSelect = function (conf) {
|
||||
onRefresh: function () {return true;}
|
||||
}, c);
|
||||
|
||||
var realParent = $(this);
|
||||
var parent = realParent;
|
||||
var realParent = $(this);
|
||||
var parent = realParent;
|
||||
|
||||
// container for lasso element
|
||||
// -> the only reason for NOT using the .pf-map is because of the zoom [scale()] feature or .pf-map
|
||||
var lassoContainer = realParent.parent();
|
||||
|
||||
var animationFrameId;
|
||||
var mouseIsDown = false;
|
||||
@@ -124,7 +128,7 @@ $.fn.dragToSelect = function (conf) {
|
||||
|
||||
// Create select box
|
||||
var selectBox = $('<div>')
|
||||
.appendTo(parent)
|
||||
.appendTo(lassoContainer)
|
||||
.attr('class', config.className)
|
||||
.css('position', 'absolute');
|
||||
|
||||
@@ -156,20 +160,6 @@ $.fn.dragToSelect = function (conf) {
|
||||
return refreshed;
|
||||
}
|
||||
|
||||
// get scroll position
|
||||
/*
|
||||
var leftScroll = 0;
|
||||
var topScroll = 0;
|
||||
|
||||
if(realParent.attr('data-scroll-left')){
|
||||
leftScroll = parseInt(realParent.attr('data-scroll-left'));
|
||||
}
|
||||
|
||||
if(realParent.attr('data-scroll-top')){
|
||||
topScroll = parseInt(realParent.attr('data-scroll-top'));
|
||||
}
|
||||
*/
|
||||
|
||||
var left = lastMousePosition.x - parentDim.left + parent[0].scrollLeft;
|
||||
var top = lastMousePosition.y - parentDim.top + parent[0].scrollTop;
|
||||
var tempWidth = selectBoxOrigin.left - left;
|
||||
@@ -220,30 +210,6 @@ $.fn.dragToSelect = function (conf) {
|
||||
}
|
||||
};
|
||||
|
||||
// Scrolls parent if needed
|
||||
var scrollPerhaps = function (e) {
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll down
|
||||
if ((e.pageY + config.scrollTH) > (parentDim.top + parentDim.height)) {
|
||||
parent[0].scrollTop += config.scrollTH;
|
||||
}
|
||||
// Scroll up
|
||||
if ((e.pageY - config.scrollTH) < parentDim.top) {
|
||||
parent[0].scrollTop -= config.scrollTH;
|
||||
}
|
||||
// Scroll right
|
||||
if ((e.pageX + config.scrollTH) > (parentDim.left + parentDim.width)) {
|
||||
parent[0].scrollLeft += config.scrollTH;
|
||||
}
|
||||
// Scroll left
|
||||
if ((e.pageX - config.scrollTH) < parentDim.left) {
|
||||
parent[0].scrollLeft -= config.scrollTH;
|
||||
}
|
||||
};
|
||||
|
||||
// Selects all the elements in the select box's range
|
||||
var selectElementsInRange = function () {
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -34,7 +34,7 @@ requirejs.config({
|
||||
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
|
||||
slidebars: 'lib/slidebars', // v2.0.2 Slidebars - side menu plugin https://www.adchsm.com/slidebars/
|
||||
jsPlumb: 'lib/jsplumb', // v2.9.3 jsPlumb main map draw plugin http://jsplumb.github.io/jsplumb/home.html
|
||||
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey
|
||||
farahey: 'lib/farahey', // v1.1.2 jsPlumb "magnetizing" plugin extension - https://github.com/ThomasChan/farahey
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
|
||||
mousewheel: 'lib/jquery.mousewheel.min', // v3.1.13 Mousewheel - https://github.com/jquery/jquery-mousewheel
|
||||
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
|
||||
|
||||
@@ -145,7 +145,6 @@ define(['jquery'], ($) => {
|
||||
unicode: ''
|
||||
}
|
||||
],
|
||||
|
||||
classes: {
|
||||
// log types
|
||||
logTypes: {
|
||||
@@ -354,17 +353,61 @@ define(['jquery'], ($) => {
|
||||
wh_critical: {
|
||||
cssClass: 'pf-map-connection-wh-critical'
|
||||
},
|
||||
frigate: {
|
||||
cssClass: 'pf-map-connection-frig',
|
||||
wh_jump_mass_s: {
|
||||
cssClass: 'pf-map-connection-wh-size-s',
|
||||
paintStyle: {
|
||||
dashstyle: '0.5 1'
|
||||
dashstyle: '0.5 1',
|
||||
strokeWidth: 3
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: 'frig',
|
||||
cssClass: ['pf-map-component-overlay', 'frig'].join(' '),
|
||||
location: 0.7
|
||||
label: '<i class="fas fa-char pf-jump-mass-s" data-char-content="S"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_m: {
|
||||
cssClass: 'pf-map-connection-wh-size-m',
|
||||
paintStyle: {
|
||||
dashstyle: '3 1'
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-m" data-char-content="M"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_l: {
|
||||
cssClass: 'pf-map-connection-wh-size-l',
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-l" data-char-content="L"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
wh_jump_mass_xl: {
|
||||
cssClass: 'pf-map-connection-wh-size-xl',
|
||||
paintStyle: {
|
||||
strokeWidth: 6
|
||||
},
|
||||
overlays: [
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-char pf-jump-mass-xl" data-char-content="XL"></i>',
|
||||
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
|
||||
location: 0.65,
|
||||
id: 'pf-map-connection-jump-mass-overlay'
|
||||
}]
|
||||
]
|
||||
},
|
||||
@@ -375,7 +418,7 @@ define(['jquery'], ($) => {
|
||||
{
|
||||
label: '<i class="fas fa-fw fa-exclamation-triangle"></i> save mass',
|
||||
cssClass: ['pf-map-component-overlay', 'mass'].join(' '),
|
||||
location: 0.3
|
||||
location: 0.35
|
||||
}]
|
||||
]
|
||||
},
|
||||
@@ -387,8 +430,8 @@ define(['jquery'], ($) => {
|
||||
cssClass: 'pf-map-connection-arrow-overlay',
|
||||
width: 12,
|
||||
length: 15,
|
||||
foldback: 0.8,
|
||||
direction: 1,
|
||||
foldback: 0.8,
|
||||
location: 0.5
|
||||
}]
|
||||
]
|
||||
@@ -408,6 +451,32 @@ define(['jquery'], ($) => {
|
||||
]
|
||||
}
|
||||
},
|
||||
wormholeSizes: {
|
||||
wh_jump_mass_xl: {
|
||||
jumpMassMin: 1000000000,
|
||||
type: 'wh_jump_mass_xl',
|
||||
class: 'pf-jump-mass-xl',
|
||||
label: 'XL'
|
||||
},
|
||||
wh_jump_mass_l: {
|
||||
jumpMassMin: 300000000,
|
||||
type: 'wh_jump_mass_l',
|
||||
class: 'pf-jump-mass-l',
|
||||
label: 'L'
|
||||
},
|
||||
wh_jump_mass_m: {
|
||||
jumpMassMin: 20000000,
|
||||
type: 'wh_jump_mass_m',
|
||||
class: 'pf-jump-mass-m',
|
||||
label: 'M'
|
||||
},
|
||||
wh_jump_mass_s: {
|
||||
jumpMassMin: 1000,
|
||||
type: 'wh_jump_mass_s',
|
||||
class: 'pf-jump-mass-s',
|
||||
label: 'S'
|
||||
}
|
||||
},
|
||||
// signature groups
|
||||
signatureGroups: {
|
||||
1: {
|
||||
|
||||
@@ -93,20 +93,25 @@ define([
|
||||
let moduleData = {
|
||||
id: config.connectionContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-plane', action: 'frigate', text: 'frigate hole'},
|
||||
{icon: 'fa-hourglass-end', action: 'wh_eol', text: 'toggle EOL'},
|
||||
{icon: 'fa-exclamation-triangle', action: 'preserve_mass', text: 'preserve mass'},
|
||||
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
|
||||
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'mass status', subitems: [
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-gray', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-orange', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
|
||||
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-redDarker', subAction: 'status_critical', subText: 'stage 3 (critical)'}
|
||||
|
||||
]},
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'change status', subitems: [
|
||||
{subIcon: 'fa-clock', subAction: 'wh_eol', subText: 'toggle EOL'},
|
||||
{subDivider: true},
|
||||
{subIcon: 'fa-circle', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
|
||||
{subIcon: 'fa-adjust', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
|
||||
{subIcon: 'fa-circle', subAction: 'status_critical', subText: 'stage 3 (critical)'}
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'wh_jump_mass_change', text: 'ship size', subitems: [
|
||||
{subIcon: 'fa-char', subChar: 'S', subAction: 'wh_jump_mass_s', subText: 'smallest ships'},
|
||||
{subIcon: 'fa-char', subChar: 'M', subAction: 'wh_jump_mass_m', subText: 'medium ships'},
|
||||
{subIcon: 'fa-char', subChar: 'L', subAction: 'wh_jump_mass_l', subText: 'larger ships'},
|
||||
{subIcon: 'fa-char', subChar: 'XL', subAction: 'wh_jump_mass_xl', subText: 'capital ships'}
|
||||
|
||||
]},
|
||||
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
|
||||
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
|
||||
|
||||
]},
|
||||
{divider: true, action: 'separator'} ,
|
||||
|
||||
@@ -1,135 +1,173 @@
|
||||
/**
|
||||
* Map "magnetizing" feature
|
||||
* jsPlumb extension used: http://morrisonpitt.com/farahey/
|
||||
* jsPlumb extension used: https://github.com/ThomasChan/farahey
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/map/util',
|
||||
'farahey'
|
||||
], function($, MapUtil){
|
||||
], ($, MapUtil) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Cached current "Magnetizer" object
|
||||
* @type {Magnetizer}
|
||||
* active magnetizer instances (cache object)
|
||||
* @type {{}}
|
||||
*/
|
||||
let m8 = null;
|
||||
let magnetizerInstances = {};
|
||||
|
||||
/**
|
||||
* init a jsPlumb (map) Element for "magnetised" function.
|
||||
* this is optional and prevents systems from being overlapped
|
||||
* magnetizer instance exists for mapId
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$.fn.initMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
let systems = mapContainer.getSystems();
|
||||
let hasInstance = mapId => magnetizerInstances.hasOwnProperty(mapId);
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* get current system offset
|
||||
* @param system
|
||||
* @returns {{left, top}}
|
||||
* @private
|
||||
*/
|
||||
let _offset = function(system){
|
||||
/**
|
||||
* get magnetizer instance by mapId
|
||||
* @param mapId
|
||||
* @returns {null}
|
||||
*/
|
||||
let getInstance = mapId => hasInstance(mapId) ? magnetizerInstances[mapId] : null;
|
||||
|
||||
let _ = function(p){
|
||||
let v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
|
||||
return {
|
||||
left:_('left'),
|
||||
top:_('top')
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* set new system offset
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
let _setOffset = function(system, o){
|
||||
let markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 &&
|
||||
o.left <= 2300
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.left = o.left + 'px';
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 &&
|
||||
o.top <= 498
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.top = o.top + 'px';
|
||||
}
|
||||
|
||||
if(markAsUpdated === true){
|
||||
MapUtil.markAsChanged($(system));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* exclude current dragged element(s) from position update
|
||||
* @param id
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
let _dragFilter = function(id){
|
||||
return !$('#' + id).is('.jsPlumb_dragged, .pf-system-locked');
|
||||
};
|
||||
|
||||
let gridConstrain = function(gridX, gridY){
|
||||
return function(id, current, delta){
|
||||
if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){
|
||||
// active grid
|
||||
return {
|
||||
left:(gridX * Math.floor( (current[0] + delta.left) / gridX )) - current[0],
|
||||
top:(gridY * Math.floor( (current[1] + delta.top) / gridY )) - current[1]
|
||||
};
|
||||
}else{
|
||||
// no grid
|
||||
return delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// main init for "magnetize" feature ------------------------------------------------------
|
||||
m8 = new Magnetizer({
|
||||
container: mapContainer,
|
||||
getContainerPosition: function(c){
|
||||
return c.offset();
|
||||
},
|
||||
getPosition:_offset,
|
||||
getSize: function(system){
|
||||
return [ $(system).outerWidth(), $(system).outerHeight() ];
|
||||
},
|
||||
getId : function(system){
|
||||
return $(system).attr('id');
|
||||
},
|
||||
setPosition:_setOffset,
|
||||
elements: systems,
|
||||
filter: _dragFilter,
|
||||
padding: [6, 6],
|
||||
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension)
|
||||
});
|
||||
/**
|
||||
* set new magnetizer instance for mapId
|
||||
* @param mapId
|
||||
* @param magnetizer
|
||||
*/
|
||||
let setInstance = (mapId, magnetizer) => {
|
||||
if(mapId && magnetizer){
|
||||
magnetizerInstances[mapId] = magnetizer;
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.destroyMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
/**
|
||||
* init new magnetizer instance for a map
|
||||
* @param mapContainer
|
||||
*/
|
||||
let initMagnetizer = mapContainer => {
|
||||
let mapId = mapContainer.data('id');
|
||||
|
||||
// remove cached "magnetizer" instance
|
||||
m8 = null;
|
||||
if(!hasInstance(mapId)){
|
||||
// magnetizer not exist -> new instance
|
||||
let systems = mapContainer.getSystems();
|
||||
|
||||
/**
|
||||
* function that takes an element from your list and returns its position as a JS object
|
||||
* @param system
|
||||
* @returns {{top: number, left: number}}
|
||||
* @private
|
||||
*/
|
||||
let _offset = system => {
|
||||
let _ = p => {
|
||||
let v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
return {left: _('left'), top: _('top')};
|
||||
};
|
||||
|
||||
/**
|
||||
* function that takes an element id and position, and applies that position to the related element
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
let _setOffset = (system, o) => {
|
||||
o.left = Math.round(o.left);
|
||||
o.top = Math.round(o.top);
|
||||
let left = o.left + 'px';
|
||||
let top = o.top + 'px';
|
||||
let markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 && o.left <= 2300 &&
|
||||
system.style.left !== left
|
||||
){
|
||||
system.style.left = left;
|
||||
markAsUpdated = true;
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 && o.top <= 1400 &&
|
||||
system.style.top !== top
|
||||
){
|
||||
system.style.top = top;
|
||||
markAsUpdated = true;
|
||||
}
|
||||
|
||||
if(markAsUpdated){
|
||||
MapUtil.markAsChanged($(system));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* filter some element8s) from being moved
|
||||
* @param systemId
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
let _dragFilter = systemId => {
|
||||
let filterClasses = ['jtk-drag', 'pf-system-locked'];
|
||||
return ![...document.getElementById(systemId).classList].some(className => filterClasses.indexOf(className) >= 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* grid snap constraint
|
||||
* @param gridX
|
||||
* @param gridY
|
||||
* @returns {Function}
|
||||
*/
|
||||
let gridConstrain = (gridX, gridY) => {
|
||||
return (id, current, delta) => {
|
||||
if(mapContainer.hasClass(MapUtil.config.mapGridClass)){
|
||||
// active grid
|
||||
return {
|
||||
left: (gridX * Math.floor( (Math.round(current[0]) + delta.left) / gridX )) - current[0],
|
||||
top: (gridY * Math.floor( (Math.round(current[1]) + delta.top) / gridY )) - current[1]
|
||||
};
|
||||
}else{
|
||||
// no grid
|
||||
delta.left = Math.round(delta.left);
|
||||
delta.top = Math.round(delta.top);
|
||||
return delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// create new magnetizer instance -------------------------------------------------------------------------
|
||||
setInstance(mapId, window.Farahey.getInstance({
|
||||
container: mapContainer,
|
||||
getContainerPosition: mapContainer => mapContainer.offset(),
|
||||
getPosition:_offset,
|
||||
getSize: system => {
|
||||
let clientRect = system.getBoundingClientRect();
|
||||
return [Math.floor(clientRect.width), Math.floor(clientRect.height)];
|
||||
},
|
||||
getId : system => system.id,
|
||||
setPosition:_setOffset,
|
||||
elements: systems.toArray(),
|
||||
filter: _dragFilter,
|
||||
padding: [3, 3],
|
||||
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension),
|
||||
executeNow: false, // no initial rearrange after initialization
|
||||
excludeFocus: true
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* destroy Magnetizer instance
|
||||
*/
|
||||
let destroyMagnetizer = mapContainer => {
|
||||
let mapId = mapContainer.data('id');
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.reset();
|
||||
delete magnetizerInstances[mapId];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -137,44 +175,50 @@ define([
|
||||
* @param map
|
||||
* @param e
|
||||
*/
|
||||
let executeAtEvent = function(map, e){
|
||||
if(m8 !== null && e ){
|
||||
m8.executeAtEvent(e);
|
||||
let executeAtEvent = (map, e) => {
|
||||
let mapContainer = $(map.getContainer());
|
||||
let mapId = mapContainer.data('id');
|
||||
let magnetizer = getInstance(mapId);
|
||||
|
||||
if(magnetizer && e){
|
||||
magnetizer.executeAtEvent(e, {
|
||||
iterations: 2,
|
||||
excludeFocus: true
|
||||
});
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* rearrange all systems of a map
|
||||
* needs "magnetization" to be active
|
||||
* @param map
|
||||
* add system to magnetizer instance
|
||||
* @param mapId
|
||||
* @param system
|
||||
* @param doNotTestForDuplicates
|
||||
*/
|
||||
let executeAtCenter = function(map){
|
||||
if(m8 !== null){
|
||||
m8.executeAtCenter();
|
||||
map.repaintEverything();
|
||||
let addElement = (mapId, system, doNotTestForDuplicates) => {
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.addElement(system, doNotTestForDuplicates);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set/update elements for "magnetization"
|
||||
* -> (e.g. new systems was added)
|
||||
* @param map
|
||||
* remove system element from magnetizer instance
|
||||
* @param mapId
|
||||
* @param system
|
||||
*/
|
||||
let setElements = function(map){
|
||||
if(m8 !== null){
|
||||
let mapContainer = $(map.getContainer());
|
||||
let systems = mapContainer.getSystems();
|
||||
m8.setElements(systems);
|
||||
|
||||
// re-arrange systems
|
||||
executeAtCenter(map);
|
||||
let removeElement = (mapId, system) => {
|
||||
let magnetizer = getInstance(mapId);
|
||||
if(magnetizer){
|
||||
magnetizer.removeElement(system);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
executeAtCenter: executeAtCenter,
|
||||
initMagnetizer: initMagnetizer,
|
||||
destroyMagnetizer: destroyMagnetizer,
|
||||
executeAtEvent: executeAtEvent,
|
||||
setElements: setElements
|
||||
addElement: addElement,
|
||||
removeElement: removeElement
|
||||
};
|
||||
});
|
||||
@@ -18,7 +18,7 @@ define([
|
||||
'app/map/scrollbar',
|
||||
'dragToSelect',
|
||||
'app/map/local'
|
||||
], ($, Init, Util, Key, bootbox, MapUtil, MapContextMenu, MapOverlay, MapOverlayUtil, System, Layout, MagnetizerWrapper, Scrollbar) => {
|
||||
], ($, Init, Util, Key, bootbox, MapUtil, MapContextMenu, MapOverlay, MapOverlayUtil, System, Layout, Magnetizer, Scrollbar) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -62,6 +62,33 @@ define([
|
||||
// -> those maps queue their updates until "pf:unlocked" event
|
||||
let mapUpdateQueue = [];
|
||||
|
||||
|
||||
// map menu options
|
||||
let mapOptions = {
|
||||
mapMagnetizer: {
|
||||
buttonId: Util.config.menuButtonMagnetizerId,
|
||||
description: 'Magnetizer',
|
||||
onEnable: Magnetizer.initMagnetizer,
|
||||
onDisable: Magnetizer.destroyMagnetizer
|
||||
},
|
||||
mapSnapToGrid : {
|
||||
buttonId: Util.config.menuButtonGridId,
|
||||
description: 'Grid snapping',
|
||||
class: 'mapGridClass'
|
||||
},
|
||||
mapSignatureOverlays : {
|
||||
buttonId: Util.config.menuButtonEndpointId,
|
||||
description: 'Endpoint overlay',
|
||||
onEnable: MapOverlay.showInfoSignatureOverlays,
|
||||
onDisable: MapOverlay.hideInfoSignatureOverlays,
|
||||
},
|
||||
mapCompact : {
|
||||
buttonId: Util.config.menuButtonCompactId,
|
||||
description: 'Compact system layout',
|
||||
class: 'mapCompactClass'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* checks mouse events on system head elements
|
||||
* -> prevents drag/drop system AND drag/drop connections on some child elements
|
||||
@@ -131,8 +158,8 @@ define([
|
||||
// check if there is a Label overlay
|
||||
let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
|
||||
if(overlay instanceof jsPlumb.Overlays.Label){
|
||||
let label = overlay.getParameter('label');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
|
||||
let labels = overlay.getParameter('signatureLabels');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,7 +702,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// save filterScopes in IndexDB
|
||||
// store filterScopes in IndexDB
|
||||
MapUtil.storeLocalData('map', mapId, 'filterScopes', filterScopes);
|
||||
MapUtil.filterMapByScopes(map, filterScopes);
|
||||
|
||||
@@ -726,7 +753,6 @@ define([
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'frigate': // set as frigate hole
|
||||
case 'preserve_mass': // set "preserve mass
|
||||
case 'wh_eol': // set "end of life"
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
|
||||
@@ -741,6 +767,14 @@ define([
|
||||
MapUtil.setConnectionWHStatus(connection, 'wh_' + newStatus);
|
||||
MapUtil.markAsChanged(connection);
|
||||
break;
|
||||
case 'wh_jump_mass_s':
|
||||
case 'wh_jump_mass_m':
|
||||
case 'wh_jump_mass_l':
|
||||
case 'wh_jump_mass_xl':
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'timer').startMapUpdateCounter();
|
||||
MapUtil.setConnectionJumpMassType(connection, action);
|
||||
MapUtil.markAsChanged(connection);
|
||||
break;
|
||||
case 'scope_wh':
|
||||
case 'scope_stargate':
|
||||
case 'scope_jumpbridge':
|
||||
@@ -969,13 +1003,13 @@ define([
|
||||
if(checkAvailability(['fresh', 'reduced', 'critical'], type)){
|
||||
MapUtil.setConnectionWHStatus(connection, type);
|
||||
}else if(connection.hasType(type) !== true){
|
||||
// additional types e.g. eol, frig, preserve mass
|
||||
// additional types e.g. eol, preserve mass
|
||||
connection.addType(type);
|
||||
}
|
||||
}
|
||||
|
||||
for(let type of removeType){
|
||||
if(checkAvailability(['wh_eol', 'frigate', 'preserve_mass', 'state_process'], type)){
|
||||
if(checkAvailability(['wh_eol', 'preserve_mass', 'state_process'], type)){
|
||||
connection.removeType(type);
|
||||
}
|
||||
}
|
||||
@@ -1178,7 +1212,6 @@ define([
|
||||
let mapContainer = mapConfig.map ? $(mapConfig.map.getContainer()) : null;
|
||||
if(mapContainer){
|
||||
let mapId = mapConfig.config.id;
|
||||
let newSystems = 0;
|
||||
|
||||
// add additional information for this map
|
||||
if(mapContainer.data('updated') !== mapConfig.config.updated.updated){
|
||||
@@ -1219,9 +1252,8 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
if( addNewSystem === true){
|
||||
if(addNewSystem === true){
|
||||
drawSystem(mapConfig.map, systemData);
|
||||
newSystems++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1324,11 +1356,6 @@ define([
|
||||
|
||||
// update local connection cache
|
||||
updateConnectionsCache(mapConfig.map);
|
||||
|
||||
// update map "magnetization" when new systems where added
|
||||
if(newSystems > 0){
|
||||
MagnetizerWrapper.setElements(mapConfig.map);
|
||||
}
|
||||
}else{
|
||||
// map is currently logged -> queue update for this map until unlock
|
||||
if( mapUpdateQueue.indexOf(mapId) === -1 ){
|
||||
@@ -1345,10 +1372,13 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(updateMapExecutor).then(payload => {
|
||||
|
||||
/**
|
||||
* apply current active scope filter
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let filterMapByScopes = payload => {
|
||||
let filterMapByScopesExecutor = (resolve, reject) => {
|
||||
// apply current active scope filter ==================================================================
|
||||
let promiseStore = MapUtil.getLocaleData('map', payload.data.mapConfig.config.id);
|
||||
promiseStore.then(dataStore => {
|
||||
let scopes = [];
|
||||
@@ -1362,7 +1392,31 @@ define([
|
||||
};
|
||||
|
||||
return new Promise(filterMapByScopesExecutor);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show signature overlays
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let showInfoSignatureOverlays = payload => {
|
||||
let showInfoSignatureOverlaysExecutor = (resolve, reject) => {
|
||||
let promiseStore = MapUtil.getLocaleData('map', payload.data.mapConfig.config.id);
|
||||
promiseStore.then(dataStore => {
|
||||
if(dataStore && dataStore.mapSignatureOverlays){
|
||||
MapOverlay.showInfoSignatureOverlays($(payload.data.mapConfig.map.getContainer()));
|
||||
}
|
||||
|
||||
resolve(payload);
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(showInfoSignatureOverlaysExecutor);
|
||||
};
|
||||
|
||||
return new Promise(updateMapExecutor)
|
||||
.then(showInfoSignatureOverlays)
|
||||
.then(filterMapByScopes);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1504,6 +1558,9 @@ define([
|
||||
// set system observer
|
||||
setSystemObserver(map, newSystem);
|
||||
|
||||
// register system to "magnetizer"
|
||||
Magnetizer.addElement(systemData.mapId, newSystem[0]);
|
||||
|
||||
// connect new system (if connection data is given)
|
||||
if(connectedSystem){
|
||||
|
||||
@@ -1736,22 +1793,26 @@ define([
|
||||
|
||||
// hidden menu actions
|
||||
if(scope === 'abyssal'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('change_scope');
|
||||
options.hidden.push('separator');
|
||||
}else if(scope === 'stargate'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('scope_stargate');
|
||||
}else if(scope === 'jumpbridge'){
|
||||
options.hidden.push('frigate');
|
||||
options.hidden.push('wh_eol');
|
||||
options.hidden.push('preserve_mass');
|
||||
options.hidden.push('change_status');
|
||||
options.hidden.push('wh_jump_mass_change');
|
||||
|
||||
options.hidden.push('scope_jumpbridge');
|
||||
}else if(scope === 'wh'){
|
||||
options.hidden.push('scope_wh');
|
||||
@@ -1761,13 +1822,14 @@ define([
|
||||
if(connection.hasType('wh_eol') === true){
|
||||
options.active.push('wh_eol');
|
||||
}
|
||||
|
||||
if(connection.hasType('frigate') === true){
|
||||
options.active.push('frigate');
|
||||
}
|
||||
if(connection.hasType('preserve_mass') === true){
|
||||
options.active.push('preserve_mass');
|
||||
}
|
||||
for(let sizeName of Object.keys(Init.wormholeSizes)){
|
||||
if(connection.hasType(sizeName)){
|
||||
options.active.push(sizeName);
|
||||
}
|
||||
}
|
||||
if(connection.hasType('wh_reduced') === true){
|
||||
options.active.push('status_reduced');
|
||||
}else if(connection.hasType('wh_critical') === true){
|
||||
@@ -1777,6 +1839,11 @@ define([
|
||||
options.active.push('status_fresh');
|
||||
}
|
||||
|
||||
// disabled menu actions
|
||||
if(connection.getParameter('sizeLocked')){
|
||||
options.disabled.push('wh_jump_mass_change');
|
||||
}
|
||||
|
||||
resolve(options);
|
||||
};
|
||||
|
||||
@@ -1864,7 +1931,7 @@ define([
|
||||
|
||||
// update system positions for "all" systems that are effected by drag&drop
|
||||
// this requires "magnet" feature to be active! (optional)
|
||||
MagnetizerWrapper.executeAtEvent(map, p.e);
|
||||
Magnetizer.executeAtEvent(map, p.e);
|
||||
},
|
||||
stop: function(params){
|
||||
let dragSystem = $(params.el);
|
||||
@@ -1967,11 +2034,7 @@ define([
|
||||
* @param sourceSystem
|
||||
*/
|
||||
let saveSystemCallback = (map, newSystemData, sourceSystem) => {
|
||||
// draw new system to map
|
||||
drawSystem(map, newSystemData, sourceSystem);
|
||||
|
||||
// re/arrange systems (prevent overlapping)
|
||||
MagnetizerWrapper.setElements(map);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2224,6 +2287,13 @@ define([
|
||||
// Notification the current zoom was changed
|
||||
newJsPlumbInstance.bind('zoom', function(zoom){
|
||||
MapOverlay.updateZoomOverlay(this);
|
||||
|
||||
// store new zoom level in IndexDB
|
||||
if(zoom === 1){
|
||||
MapUtil.deleteLocalData('map', mapId, 'mapZoom');
|
||||
}else{
|
||||
MapUtil.storeLocalData('map', mapId, 'mapZoom', zoom);
|
||||
}
|
||||
});
|
||||
|
||||
// ========================================================================================================
|
||||
@@ -2523,7 +2593,7 @@ define([
|
||||
let mapElement = $(this);
|
||||
|
||||
// get map menu config options
|
||||
let data = MapUtil.mapOptions[mapOption.option];
|
||||
let data = mapOptions[mapOption.option];
|
||||
|
||||
let promiseStore = MapUtil.getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(function(dataStore){
|
||||
@@ -2538,50 +2608,50 @@ define([
|
||||
dataExists = true;
|
||||
}
|
||||
|
||||
if(dataExists === mapOption.toggle){
|
||||
if(dataExists === this.mapOption.toggle){
|
||||
|
||||
// toggle button class
|
||||
button.removeClass('active');
|
||||
|
||||
// toggle map class (e.g. for grid)
|
||||
if(this.data.class){
|
||||
this.mapElement.removeClass( MapUtil.config[this.data.class] );
|
||||
this.mapElement.removeClass(MapUtil.config[this.data.class]);
|
||||
}
|
||||
|
||||
// call optional jQuery extension on mapElement
|
||||
if(this.data.onDisable){
|
||||
$.fn[ this.data.onDisable ].apply(this.mapElement);
|
||||
if(this.data.onDisable && !this.mapOption.skipOnDisable){
|
||||
this.data.onDisable(this.mapElement);
|
||||
}
|
||||
|
||||
// show map overlay info icon
|
||||
MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'hide');
|
||||
|
||||
// delete map option
|
||||
MapUtil.deleteLocalData('map', this.mapElement.data('id'), this.mapOption.option );
|
||||
MapUtil.deleteLocalData('map', this.mapElement.data('id'), this.mapOption.option);
|
||||
}else{
|
||||
// toggle button class
|
||||
button.addClass('active');
|
||||
|
||||
// toggle map class (e.g. for grid)
|
||||
if(this.data.class){
|
||||
this.mapElement.addClass( MapUtil.config[this.data.class] );
|
||||
this.mapElement.addClass(MapUtil.config[this.data.class]);
|
||||
}
|
||||
|
||||
// call optional jQuery extension on mapElement
|
||||
if(this.data.onEnable){
|
||||
$.fn[ this.data.onEnable ].apply(this.mapElement);
|
||||
if(this.data.onEnable && !this.mapOption.skipOnEnable){
|
||||
this.data.onEnable(this.mapElement);
|
||||
}
|
||||
|
||||
// hide map overlay info icon
|
||||
MapOverlayUtil.getMapOverlay(this.mapElement, 'info').updateOverlayIcon(this.mapOption.option, 'show');
|
||||
|
||||
// store map option
|
||||
MapUtil.storeLocalData('map', this.mapElement.data('id'), this.mapOption.option, 1 );
|
||||
MapUtil.storeLocalData('map', this.mapElement.data('id'), this.mapOption.option, 1);
|
||||
|
||||
notificationText = 'enabled';
|
||||
}
|
||||
|
||||
if(mapOption.toggle){
|
||||
if(this.mapOption.toggle){
|
||||
Util.showNotify({title: this.data.description, text: notificationText, type: 'info'});
|
||||
}
|
||||
}.bind({
|
||||
@@ -3009,7 +3079,8 @@ define([
|
||||
let mapElement = $(mapConfig.map.getContainer());
|
||||
MapUtil.setMapDefaultOptions(mapElement, mapConfig.config)
|
||||
.then(payload => MapUtil.visualizeMap(mapElement, 'show'))
|
||||
.then(payload => MapUtil.scrollToDefaultPosition(mapElement))
|
||||
.then(payload => MapUtil.zoomToDefaultScale(mapConfig.map))
|
||||
.then(payload => MapUtil.scrollToDefaultPosition(mapConfig.map))
|
||||
.then(payload => {
|
||||
Util.showNotify({title: 'Map initialized', text: mapConfig.config.name + ' - loaded', type: 'success'});
|
||||
})
|
||||
@@ -3039,7 +3110,7 @@ define([
|
||||
*/
|
||||
let loadMapExecutor = (resolve, reject) => {
|
||||
// init jsPlumb
|
||||
jsPlumb.ready(function(){
|
||||
jsPlumb.ready(() => {
|
||||
// get new map instance or load existing
|
||||
mapConfig.map = getMapInstance(mapConfig.config.id);
|
||||
|
||||
|
||||
@@ -11,81 +11,93 @@ define([
|
||||
], ($, Init, Util, MapOverlayUtil, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* get MapObject (jsPlumb) from mapElement
|
||||
* @param mapElement
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromMapElement = mapElement => {
|
||||
let Map = require('app/map/map');
|
||||
return Map.getMapInstance(mapElement.data('id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* get map object (jsPlumb) from iconElement
|
||||
* @param overlayIcon
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromOverlayIcon = overlayIcon => {
|
||||
let mapElement = Util.getMapElementFromOverlay(overlayIcon);
|
||||
return getMapObjectFromMapElement(mapElement);
|
||||
return MapUtil.getMapInstance(Util.getMapElementFromOverlay(overlayIcon).data('id'));
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlay to endpoint with signature data
|
||||
* add/update endpoints with overlays from signature mapping
|
||||
* @param endpoint
|
||||
* @param labelData
|
||||
*/
|
||||
let addEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let label = labelData.labels.join(', ');
|
||||
let name = labelData.names.join(', ');
|
||||
let updateEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let labels = labelData.labels;
|
||||
let names = labelData.names;
|
||||
let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
|
||||
|
||||
if(overlay instanceof jsPlumb.Overlays.Label){
|
||||
// update existing overlay
|
||||
if(
|
||||
label !== overlay.getParameter('label') ||
|
||||
name !== overlay.getParameter('signatureName')
|
||||
!labels.equalValues(overlay.getParameter('signatureLabels')) ||
|
||||
!names.equalValues(overlay.getParameter('signatureNames'))
|
||||
){
|
||||
// update label only on label changes
|
||||
overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(label));
|
||||
overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(labels));
|
||||
overlay.setParameter('fullSize', false);
|
||||
overlay.setParameter('label', label);
|
||||
overlay.setParameter('signatureName', name);
|
||||
overlay.updateClasses(label.length ? 'small' : 'icon', label.length ? 'icon' : 'small');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
|
||||
overlay.setParameter('signatureLabels', labels);
|
||||
overlay.setParameter('signatureNames', names);
|
||||
overlay.updateClasses(labels.length ? 'small' : 'icon', labels.length ? 'icon' : 'small');
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels));
|
||||
}
|
||||
}else{
|
||||
// add new overlay
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(label),
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(labels),
|
||||
id: MapOverlayUtil.config.endpointOverlayId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, labels.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels),
|
||||
events: {
|
||||
toggleSize: function(fullSize){
|
||||
let signatureName = this.getParameter('signatureName');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureName){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureName + '</span>');
|
||||
let signatureNames = this.getParameter('signatureNames');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureNames.length){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureNames.join(', ') + '</span>');
|
||||
this.setParameter('fullSize', true);
|
||||
}else if(this.getParameter('fullSize')){
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('signatureLabels')));
|
||||
this.setParameter('fullSize', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
fullSize: false,
|
||||
label: label,
|
||||
signatureName: name
|
||||
signatureLabels: labels,
|
||||
signatureNames: names
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get overlay parameters for connection overlay (type 'diamond' or 'arrow')
|
||||
* @param overlayType
|
||||
* @param direction
|
||||
* @returns {{length: number, foldback: number, direction: number}}
|
||||
*/
|
||||
let getConnectionArrowOverlayParams = (overlayType, direction = 1) => {
|
||||
switch(overlayType){
|
||||
case 'arrow':
|
||||
return {
|
||||
length: 15,
|
||||
direction: direction,
|
||||
foldback: 0.8
|
||||
};
|
||||
default: // diamond
|
||||
return {
|
||||
length: 10,
|
||||
direction: 1,
|
||||
foldback: 2
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlays to connections (signature based data)
|
||||
* @param map
|
||||
@@ -93,26 +105,18 @@ define([
|
||||
*/
|
||||
let updateInfoSignatureOverlays = (map, connectionsData) => {
|
||||
let type = 'info_signature';
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
|
||||
connectionsData = Util.arrayToObject(connectionsData);
|
||||
|
||||
map.batch(function(){
|
||||
map.getAllConnections().forEach(function(connection){
|
||||
map.batch(() => {
|
||||
map.getAllConnections().forEach(connection => {
|
||||
let connectionId = connection.getParameter('connectionId');
|
||||
let sourceEndpoint = connection.endpoints[0];
|
||||
let targetEndpoint = connection.endpoints[1];
|
||||
|
||||
let signatureTypeData = {
|
||||
source: {
|
||||
names: [],
|
||||
labels: []
|
||||
},
|
||||
target: {
|
||||
names: [],
|
||||
labels: []
|
||||
}
|
||||
};
|
||||
let connectionData = connectionsData.hasOwnProperty(connectionId) ? connectionsData[connectionId] : undefined;
|
||||
let signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sizeLockedBySignature = false;
|
||||
|
||||
if(connection.scope === 'wh'){
|
||||
if(!connection.hasType(type)){
|
||||
@@ -127,49 +131,49 @@ define([
|
||||
connection.canvas.appendChild(overlayArrow.path);
|
||||
}
|
||||
|
||||
let overlayType = 'Diamond'; // not specified
|
||||
// since there "could" be multiple sig labels on each endpoint,
|
||||
// there can only one "primary label picked up for wormhole jump mass detection!
|
||||
let primLabel;
|
||||
|
||||
let overlayType = 'diamond'; // not specified
|
||||
let arrowDirection = 1;
|
||||
let arrowFoldback = 2;
|
||||
|
||||
if(connectionsData.hasOwnProperty(connectionId)){
|
||||
if(connectionData && connectionData.signatures){
|
||||
// signature data found for current connection
|
||||
signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionsData[connectionId]);
|
||||
|
||||
let sourceLabel = signatureTypeData.source.labels;
|
||||
let targetLabel = signatureTypeData.target.labels;
|
||||
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ------------------------------------
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ----------------------------
|
||||
if(
|
||||
(sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.includes('K162') && targetLabel.includes('K162')) ||
|
||||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
|
||||
(
|
||||
sourceLabel.length > 0 && targetLabel.length > 0 &&
|
||||
sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
|
||||
!sourceLabel.includes('K162') && !targetLabel.includes('K162')
|
||||
)
|
||||
){
|
||||
// unknown direction
|
||||
overlayType = 'Diamond'; // not specified
|
||||
arrowDirection = 1;
|
||||
arrowFoldback = 2;
|
||||
// unknown direction -> show default 'diamond' overlay
|
||||
overlayType = 'diamond';
|
||||
}else if(
|
||||
(sourceLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
|
||||
(sourceLabel.includes('K162')) ||
|
||||
(sourceLabel.length === 0 && !targetLabel.includes('K162'))
|
||||
){
|
||||
// convert default arrow direction
|
||||
overlayType = 'Arrow';
|
||||
overlayType = 'arrow';
|
||||
arrowDirection = -1;
|
||||
arrowFoldback = 0.8;
|
||||
|
||||
primLabel = targetLabel.find(label => label !== 'K162');
|
||||
}else{
|
||||
// default arrow direction is fine
|
||||
overlayType = 'Arrow';
|
||||
arrowDirection = 1;
|
||||
arrowFoldback = 0.8;
|
||||
overlayType = 'arrow';
|
||||
|
||||
primLabel = sourceLabel.find(label => label !== 'K162');
|
||||
}
|
||||
}
|
||||
|
||||
// class changes must be done on "connection" itself not on "overlayArrow"
|
||||
// -> because Arrow might not be rendered to map at this point (if it does not exist already)
|
||||
if(overlayType === 'Arrow'){
|
||||
if(overlayType === 'arrow'){
|
||||
connection.updateClasses(
|
||||
MapOverlayUtil.config.connectionArrowOverlaySuccessClass,
|
||||
MapOverlayUtil.config.connectionArrowOverlayDangerClass
|
||||
@@ -181,20 +185,39 @@ define([
|
||||
);
|
||||
}
|
||||
|
||||
overlayArrow.updateFrom({
|
||||
direction: arrowDirection,
|
||||
foldback: arrowFoldback
|
||||
});
|
||||
overlayArrow.updateFrom(getConnectionArrowOverlayParams(overlayType, arrowDirection));
|
||||
|
||||
// add endpoint overlays --------------------------------------------------------------------------
|
||||
addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
// update/add endpoint overlays -------------------------------------------------------------------
|
||||
updateEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
updateEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
|
||||
// fix/overwrite existing jump mass connection type -----------------------------------------------
|
||||
// if a connection type for "jump mass" (e.g. S, M, L, XL) is set for this connection
|
||||
// we should check/compare it with the current primary signature label from signature mapping
|
||||
// and change it if necessary
|
||||
if(Init.wormholes.hasOwnProperty(primLabel)){
|
||||
// connection size from mapped signature
|
||||
sizeLockedBySignature = true;
|
||||
|
||||
let wormholeData = Object.assign({}, Init.wormholes[primLabel]);
|
||||
if(
|
||||
wormholeData.size && wormholeData.size.type &&
|
||||
!connection.hasType(wormholeData.size.type)
|
||||
){
|
||||
MapOverlayUtil.getMapOverlay(connection.canvas, 'timer').startMapUpdateCounter();
|
||||
MapUtil.setConnectionJumpMassType(connection, wormholeData.size.type);
|
||||
MapUtil.markAsChanged(connection);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// connection is not 'wh' scope
|
||||
if(connection.hasType(type)){
|
||||
connection.removeType(type);
|
||||
}
|
||||
}
|
||||
|
||||
// lock/unlock connection for manual size changes (from contextmenu)
|
||||
connection.setParameter('sizeLocked', sizeLockedBySignature);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -246,58 +269,45 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* git signature data that is linked to a connection for a mapId
|
||||
* @param mapElement
|
||||
* @param callback
|
||||
* get overlay icon from e.g. mapElement
|
||||
* @param element
|
||||
* @param iconClass
|
||||
* @param overlayType
|
||||
* @returns {*}
|
||||
*/
|
||||
let getConnectionSignatureData = (mapElement, callback) => {
|
||||
let mapOverlay = MapOverlayUtil.getMapOverlay(mapElement, 'info');
|
||||
let overlayConnectionIcon = mapOverlay.find('.pf-map-overlay-endpoint');
|
||||
|
||||
showLoading(overlayConnectionIcon);
|
||||
|
||||
let requestData = {
|
||||
mapId: mapElement.data('id'),
|
||||
addData : ['signatures'],
|
||||
filterData : ['signatures']
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getMapConnectionData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
mapElement: mapElement,
|
||||
overlayConnectionIcon: overlayConnectionIcon
|
||||
}
|
||||
}).done(function(connectionsData){
|
||||
let map = getMapObjectFromMapElement(this.mapElement);
|
||||
callback(map, connectionsData);
|
||||
}).always(function(){
|
||||
hideLoading(this.overlayConnectionIcon);
|
||||
});
|
||||
let getOverlayIcon = (element, iconClass, overlayType = 'info') => {
|
||||
return MapOverlayUtil.getMapOverlay(element, overlayType).find('.' + iconClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* showInfoSignatureOverlays
|
||||
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
|
||||
*/
|
||||
$.fn.showInfoSignatureOverlays = function(){
|
||||
let mapElement = $(this);
|
||||
getConnectionSignatureData(mapElement, updateInfoSignatureOverlays);
|
||||
let showInfoSignatureOverlays = mapElement => {
|
||||
let mapId = mapElement.data('id');
|
||||
let map = MapUtil.getMapInstance(mapId);
|
||||
let mapData = Util.getCurrentMapData(mapId);
|
||||
let connectionsData = Util.getObjVal(mapData, 'data.connections');
|
||||
|
||||
if(connectionsData){
|
||||
let overlayIcon = getOverlayIcon(mapElement, options.mapSignatureOverlays.class);
|
||||
showLoading(overlayIcon);
|
||||
updateInfoSignatureOverlays(map, connectionsData);
|
||||
hideLoading(overlayIcon);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hideInfoSignatureOverlays
|
||||
* -> see showInfoSignatureOverlays()
|
||||
*/
|
||||
$.fn.hideInfoSignatureOverlays = function(){
|
||||
let map = getMapObjectFromMapElement($(this));
|
||||
let hideInfoSignatureOverlays = mapElement => {
|
||||
let mapId = mapElement.data('id');
|
||||
let map = MapUtil.getMapInstance(mapId);
|
||||
let type = 'info_signature';
|
||||
|
||||
map.batch(function(){
|
||||
map.getAllConnections().forEach(function(connection){
|
||||
map.batch(() => {
|
||||
map.getAllConnections().forEach(connection => {
|
||||
let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
|
||||
if(overlayArrow){
|
||||
@@ -382,20 +392,11 @@ define([
|
||||
}
|
||||
}
|
||||
},
|
||||
mapEndpoint: {
|
||||
mapSignatureOverlays: {
|
||||
title: 'refresh signature overlays',
|
||||
trigger: 'refresh',
|
||||
class: 'pf-map-overlay-endpoint',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-link'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
mapElement.showInfoSignatureOverlays();
|
||||
},
|
||||
out: function(e){
|
||||
// just "refresh" on hover
|
||||
}
|
||||
}
|
||||
iconClass: ['fas', 'fa-fw', 'fa-link']
|
||||
},
|
||||
mapCompact: {
|
||||
title: 'compact layout',
|
||||
@@ -427,8 +428,8 @@ define([
|
||||
|
||||
// format overlay label
|
||||
let labels = [
|
||||
'<i class="fas fa-fw fa-plus-square"></i> ' + formatTimeParts(createdDiff),
|
||||
'<i class="fas fa-fw fa-pen-square"></i> ' + formatTimeParts(updatedDiff)
|
||||
formatTimeParts(createdDiff) + ' <i class="fas fa-fw fa-plus-square"></i>',
|
||||
formatTimeParts(updatedDiff) + ' <i class="fas fa-fw fa-pen-square"></i>'
|
||||
];
|
||||
|
||||
// add label overlay --------------------------------------------------------------------------
|
||||
@@ -437,7 +438,7 @@ define([
|
||||
{
|
||||
label: labels.join('<br>'),
|
||||
id: MapOverlayUtil.config.connectionOverlayWhId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small'].join(' '),
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small', 'text-right'].join(' '),
|
||||
location: 0.35
|
||||
}
|
||||
]);
|
||||
@@ -457,7 +458,7 @@ define([
|
||||
title: 'EOL timer',
|
||||
trigger: 'hover',
|
||||
class: 'pf-map-overlay-connection-eol',
|
||||
iconClass: ['far', 'fa-fw', 'fa-clock'],
|
||||
iconClass: ['fas', 'fa-fw', 'fa-hourglass-end'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
@@ -472,7 +473,7 @@ define([
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: '<i class="far fa-fw fa-clock"></i> ' + formatTimeParts(diff),
|
||||
label: '<i class="fas fa-fw fa-hourglass-end"></i> ' + formatTimeParts(diff),
|
||||
id: MapOverlayUtil.config.connectionOverlayEolId,
|
||||
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'eol'].join(' '),
|
||||
location: 0.25
|
||||
@@ -542,7 +543,7 @@ define([
|
||||
let percentPerCount = 100 / maxSeconds;
|
||||
|
||||
// update counter
|
||||
let updateChart = function(tempSeconds){
|
||||
let updateChart = tempSeconds => {
|
||||
let pieChart = counterChart.data('easyPieChart');
|
||||
|
||||
if(pieChart !== undefined){
|
||||
@@ -552,7 +553,7 @@ define([
|
||||
};
|
||||
|
||||
// main timer function is called on any counter update
|
||||
let timer = function(mapUpdateCounter){
|
||||
let timer = mapUpdateCounter => {
|
||||
// decrease timer
|
||||
let currentSeconds = counterChart.data('currentSeconds');
|
||||
currentSeconds--;
|
||||
@@ -883,6 +884,8 @@ define([
|
||||
};
|
||||
|
||||
return {
|
||||
showInfoSignatureOverlays: showInfoSignatureOverlays,
|
||||
hideInfoSignatureOverlays: hideInfoSignatureOverlays,
|
||||
updateZoomOverlay: updateZoomOverlay,
|
||||
initMapDebugOverlays: initMapDebugOverlays
|
||||
};
|
||||
|
||||
@@ -9,8 +9,9 @@ define([
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/layout'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout) => {
|
||||
'app/map/layout',
|
||||
'app/map/magnetizing'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout, Magnetizer) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -702,6 +703,9 @@ define([
|
||||
// remove connections do not fire a "connectionDetached" event
|
||||
map.deleteConnectionsForElement(system, {fireEvent: false});
|
||||
|
||||
// unregister from "magnetizer"
|
||||
Magnetizer.removeElement(system.data('mapid'), system[0]);
|
||||
|
||||
// destroy tooltip/popover
|
||||
system.toggleSystemTooltip('destroy', {});
|
||||
system.destroyPopover(true);
|
||||
|
||||
@@ -41,32 +41,6 @@ define([
|
||||
tableCellEllipsis100Class: 'pf-table-cell-100'
|
||||
};
|
||||
|
||||
// map menu options
|
||||
let mapOptions = {
|
||||
mapMagnetizer: {
|
||||
buttonId: Util.config.menuButtonMagnetizerId,
|
||||
description: 'Magnetizer',
|
||||
onEnable: 'initMagnetizer', // jQuery extension function
|
||||
onDisable: 'destroyMagnetizer' // jQuery extension function
|
||||
},
|
||||
mapSnapToGrid : {
|
||||
buttonId: Util.config.menuButtonGridId,
|
||||
description: 'Grid snapping',
|
||||
class: 'mapGridClass'
|
||||
},
|
||||
mapEndpoint : {
|
||||
buttonId: Util.config.menuButtonEndpointId,
|
||||
description: 'Endpoint overlay',
|
||||
onEnable: 'showInfoSignatureOverlays', // jQuery extension function
|
||||
onDisable: 'hideInfoSignatureOverlays' // jQuery extension function
|
||||
},
|
||||
mapCompact : {
|
||||
buttonId: Util.config.menuButtonCompactId,
|
||||
description: 'Compact system layout',
|
||||
class: 'mapCompactClass'
|
||||
}
|
||||
};
|
||||
|
||||
// active jsPlumb instances currently running =====================================================================
|
||||
let activeInstances = {};
|
||||
|
||||
@@ -518,6 +492,7 @@ define([
|
||||
|
||||
if(
|
||||
connection &&
|
||||
connectionData &&
|
||||
connectionData.signatures // signature data is required...
|
||||
){
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
@@ -556,7 +531,7 @@ define([
|
||||
|
||||
if(flattenSigTypeNames.hasOwnProperty(signatureData.typeId)){
|
||||
let label = flattenSigTypeNames[signatureData.typeId];
|
||||
// shorten label, just take the in game name
|
||||
// shorten label, just take the ingame name
|
||||
label = label.substr(0, label.indexOf(' '));
|
||||
signatureTypeData[tmpSystemType].names.push(signatureData.name);
|
||||
signatureTypeData[tmpSystemType].labels.push(label);
|
||||
@@ -574,13 +549,13 @@ define([
|
||||
* -> Coordinates are relative to the Endpoint (not the system!)
|
||||
* -> jsPlumb specific format
|
||||
* @param endpoint
|
||||
* @param label
|
||||
* @param labels
|
||||
* @returns {number[]}
|
||||
*/
|
||||
let getEndpointOverlaySignatureLocation = (endpoint, label) => {
|
||||
let chars = label.length ? label.length : 2;
|
||||
let xLeft = chars === 2 ? -0.5 : chars <= 4 ? -1 : 3;
|
||||
let xRight = chars === 2 ? +1.5 : chars <= 4 ? +2.20 : 3;
|
||||
let getEndpointOverlaySignatureLocation = (endpoint, labels) => {
|
||||
let count = labels.length;
|
||||
let xLeft = count ? count === 1 ? -1.00 : 3 : -0.5;
|
||||
let xRight = count ? count === 1 ? +2.20 : 3 : +1.5;
|
||||
|
||||
switch(endpoint.anchor.getCurrentFace()){
|
||||
case 'top': return [0.5, -0.75];
|
||||
@@ -593,24 +568,25 @@ define([
|
||||
|
||||
/**
|
||||
* get overlay HTML for connection endpoints by Label array
|
||||
* @param label
|
||||
* @param labels
|
||||
* @returns {string}
|
||||
*/
|
||||
let formatEndpointOverlaySignatureLabel = label => {
|
||||
let formatEndpointOverlaySignatureLabel = labels => {
|
||||
// default K162 in label array, or multiple labels
|
||||
let colorClass = 'txt-color-grayLighter';
|
||||
let label = labels.join(', ');
|
||||
|
||||
if(label.length > 0){
|
||||
// check if multiple labels found => conflict
|
||||
if( label.includes(', ') ){
|
||||
colorClass = 'txt-color-orangeLight';
|
||||
}else if( !label.includes('K162') ){
|
||||
colorClass = 'txt-color-yellow';
|
||||
}
|
||||
}else{
|
||||
if(labels.length === 0){
|
||||
// endpoint not connected with a signature
|
||||
label = '<i class="fas fa-question-circle"></i>';
|
||||
colorClass = 'txt-color-red';
|
||||
}else if(
|
||||
labels.length === 1 &&
|
||||
!labels.includes('K162')
|
||||
){
|
||||
colorClass = Init.wormholes[labels[0]].class;
|
||||
}
|
||||
|
||||
return '<span class="txt-color ' + colorClass + '">' + label + '</span>';
|
||||
};
|
||||
|
||||
@@ -639,62 +615,64 @@ define([
|
||||
*/
|
||||
let filterMapByScopes = (map, scopes) => {
|
||||
if(map){
|
||||
let mapElement = $(map.getContainer());
|
||||
let allSystems = mapElement.getSystems();
|
||||
let allConnections = map.getAllConnections();
|
||||
map.batch(() => {
|
||||
let mapElement = $(map.getContainer());
|
||||
let allSystems = mapElement.getSystems();
|
||||
let allConnections = map.getAllConnections();
|
||||
|
||||
if(scopes && scopes.length){
|
||||
// filter connections -------------------------------------------------------------------------------------
|
||||
let visibleSystems = [];
|
||||
let visibleConnections = searchConnectionsByScopeAndType(map, scopes);
|
||||
if(scopes && scopes.length){
|
||||
// filter connections -------------------------------------------------------------------------------------
|
||||
let visibleSystems = [];
|
||||
let visibleConnections = searchConnectionsByScopeAndType(map, scopes);
|
||||
|
||||
for(let connection of allConnections){
|
||||
if(visibleConnections.indexOf(connection) >= 0){
|
||||
setConnectionVisible(connection, true);
|
||||
// source/target system should always be visible -> even if filter scope not matches system type
|
||||
if(visibleSystems.indexOf(connection.endpoints[0].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[0].element);
|
||||
for(let connection of allConnections){
|
||||
if(visibleConnections.indexOf(connection) >= 0){
|
||||
setConnectionVisible(connection, true);
|
||||
// source/target system should always be visible -> even if filter scope not matches system type
|
||||
if(visibleSystems.indexOf(connection.endpoints[0].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[0].element);
|
||||
}
|
||||
if(visibleSystems.indexOf(connection.endpoints[1].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[1].element);
|
||||
}
|
||||
}else{
|
||||
setConnectionVisible(connection, false);
|
||||
}
|
||||
if(visibleSystems.indexOf(connection.endpoints[1].element) < 0){
|
||||
visibleSystems.push(connection.endpoints[1].element);
|
||||
}
|
||||
}else{
|
||||
setConnectionVisible(connection, false);
|
||||
}
|
||||
}
|
||||
|
||||
// filter systems -----------------------------------------------------------------------------------------
|
||||
let visibleTypeIds = [];
|
||||
if(scopes.indexOf('wh') >= 0){
|
||||
visibleTypeIds.push(1);
|
||||
}
|
||||
if(scopes.indexOf('abyssal') >= 0){
|
||||
visibleTypeIds.push(4);
|
||||
}
|
||||
// filter systems -----------------------------------------------------------------------------------------
|
||||
let visibleTypeIds = [];
|
||||
if(scopes.indexOf('wh') >= 0){
|
||||
visibleTypeIds.push(1);
|
||||
}
|
||||
if(scopes.indexOf('abyssal') >= 0){
|
||||
visibleTypeIds.push(4);
|
||||
}
|
||||
|
||||
for(let system of allSystems){
|
||||
if(
|
||||
visibleTypeIds.indexOf($(system).data('typeId')) >= 0 ||
|
||||
visibleSystems.indexOf(system) >= 0
|
||||
){
|
||||
for(let system of allSystems){
|
||||
if(
|
||||
visibleTypeIds.indexOf($(system).data('typeId')) >= 0 ||
|
||||
visibleSystems.indexOf(system) >= 0
|
||||
){
|
||||
setSystemVisible(system, map, true);
|
||||
}else{
|
||||
setSystemVisible(system, map, false);
|
||||
}
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'show');
|
||||
}else{
|
||||
// clear filter
|
||||
for(let system of allSystems){
|
||||
setSystemVisible(system, map, true);
|
||||
}else{
|
||||
setSystemVisible(system, map, false);
|
||||
}
|
||||
}
|
||||
for(let connection of allConnections){
|
||||
setConnectionVisible(connection, true);
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'show');
|
||||
}else{
|
||||
// clear filter
|
||||
for(let system of allSystems){
|
||||
setSystemVisible(system, map, true);
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'hide');
|
||||
}
|
||||
for(let connection of allConnections){
|
||||
setConnectionVisible(connection, true);
|
||||
}
|
||||
|
||||
MapOverlayUtil.getMapOverlay(mapElement, 'info').updateOverlayIcon('filter', 'hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -761,12 +739,11 @@ define([
|
||||
'height': scrollableHeight ? scaledHeight + 'px' : (wrapperHeight) + 'px',
|
||||
});
|
||||
|
||||
|
||||
let mapWrapperElement = mapContainer.closest('.mCustomScrollbar');
|
||||
if(scrollableWidth && scrollableHeight){
|
||||
mapWrapperElement.mCustomScrollbar('update');
|
||||
}else{
|
||||
mapWrapperElement.mCustomScrollbar('scrollTo', '#pf-map-1', {
|
||||
mapWrapperElement.mCustomScrollbar('scrollTo', '#' + mapContainer.attr('id'), {
|
||||
scrollInertia: 0,
|
||||
scrollEasing: 'linear',
|
||||
timeout: 0,
|
||||
@@ -844,40 +821,45 @@ define([
|
||||
* with the addition of respecting active Arrow overlay direction
|
||||
* @param action
|
||||
* @param connection
|
||||
* @param type
|
||||
* @param types
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let changeConnectionType = (action, connection, type, params = {}, doNotRepaint = false) => {
|
||||
// check for active Arrow overlay
|
||||
let overlayArrow, overlayArrowParams;
|
||||
if(
|
||||
type !== 'info_signature' &&
|
||||
connection.hasType('info_signature')
|
||||
){
|
||||
overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
if(overlayArrow){
|
||||
overlayArrowParams = {
|
||||
direction: overlayArrow.direction,
|
||||
foldback: overlayArrow.foldback,
|
||||
};
|
||||
let changeConnectionTypes = (action, connection, types = [], params = [], doNotRepaint = false) => {
|
||||
|
||||
if(connection && types.length){
|
||||
// check for active Arrow overlay
|
||||
let overlayArrow, overlayArrowParams;
|
||||
if(
|
||||
!types.includes('info_signature') &&
|
||||
connection.hasType('info_signature')
|
||||
){
|
||||
overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
|
||||
if(overlayArrow){
|
||||
overlayArrowParams = {
|
||||
direction: overlayArrow.direction,
|
||||
foldback: overlayArrow.foldback,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the new type
|
||||
connection[action](type, params, doNotRepaint);
|
||||
for(let i = 0; i < types.length; i++){
|
||||
// change the new type
|
||||
connection[action](types[i], typeof params[i] === 'object' ? params[i] : {}, doNotRepaint);
|
||||
}
|
||||
|
||||
// change Arrow overlay data back to initial direction
|
||||
if(
|
||||
overlayArrow &&
|
||||
(
|
||||
overlayArrow.direction !== overlayArrowParams.direction ||
|
||||
overlayArrow.foldback !== overlayArrowParams.foldback
|
||||
)
|
||||
){
|
||||
overlayArrow.updateFrom(overlayArrowParams);
|
||||
if(!doNotRepaint){
|
||||
connection.repaint();
|
||||
// change Arrow overlay data back to initial direction
|
||||
if(
|
||||
overlayArrow &&
|
||||
(
|
||||
overlayArrow.direction !== overlayArrowParams.direction ||
|
||||
overlayArrow.foldback !== overlayArrowParams.foldback
|
||||
)
|
||||
){
|
||||
overlayArrow.updateFrom(overlayArrowParams);
|
||||
if(!doNotRepaint){
|
||||
connection.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -889,8 +871,12 @@ define([
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let addConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('addType', connection, type, params, doNotRepaint);
|
||||
let addConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
addConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
let addConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||||
changeConnectionTypes('addType', connection, types, params, doNotRepaint);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -900,12 +886,16 @@ define([
|
||||
* @param params
|
||||
* @param doNotRepaint
|
||||
*/
|
||||
let removeConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('removeType', connection, type, params, doNotRepaint);
|
||||
let removeConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
removeConnectionTypes(connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
let toggleConnectionType = (connection, type, params = {}, doNotRepaint = false) => {
|
||||
changeConnectionType('toggleType', connection, type, params, doNotRepaint);
|
||||
let removeConnectionTypes = (connection, types = [], params = [], doNotRepaint = false) => {
|
||||
changeConnectionTypes('removeType', connection, types, params, doNotRepaint);
|
||||
};
|
||||
|
||||
let toggleConnectionType = (connection, type, params, doNotRepaint = false) => {
|
||||
changeConnectionTypes('toggleType', connection, [type], typeof params === 'object' ? [params] : [], doNotRepaint);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1136,10 +1126,10 @@ define([
|
||||
* @param types
|
||||
* @returns {string[]}
|
||||
*/
|
||||
let getConnectionFakeClassesByTypes = (types) => {
|
||||
let getConnectionFakeClassesByTypes = types => {
|
||||
let connectionClasses = ['pf-fake-connection'];
|
||||
for(let i = 0; i < types.length; i++){
|
||||
connectionClasses.push(getConnectionInfo( types[i], 'cssClass'));
|
||||
connectionClasses.push(getConnectionInfo(types[i], 'cssClass'));
|
||||
}
|
||||
return connectionClasses;
|
||||
};
|
||||
@@ -1147,9 +1137,9 @@ define([
|
||||
/**
|
||||
* get all direct connections between two given systems
|
||||
* @param map
|
||||
* @param {JQuery} systemA
|
||||
* @param {JQuery} systemB
|
||||
* @returns {Array}
|
||||
* @param systemA
|
||||
* @param systemB
|
||||
* @returns {*[]}
|
||||
*/
|
||||
let checkForConnection = (map, systemA, systemB) => {
|
||||
let connections = [];
|
||||
@@ -1224,6 +1214,31 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set/change connection jump mass of a wormhole
|
||||
* @param connection
|
||||
* @param mass
|
||||
*/
|
||||
let setConnectionJumpMassType = (connection, mass) => {
|
||||
let allMassTypes = ['wh_jump_mass_s', 'wh_jump_mass_m', 'wh_jump_mass_l', 'wh_jump_mass_xl'];
|
||||
let addMassType = [];
|
||||
let removeMassTypes = [];
|
||||
|
||||
connection._jsPlumb.instance.batch(() => {
|
||||
if(allMassTypes.includes(mass)){
|
||||
if(connection.hasType(mass)){
|
||||
removeMassTypes = allMassTypes;
|
||||
}else{
|
||||
addMassType = [mass];
|
||||
removeMassTypes = allMassTypes.filter(e => e !== mass);
|
||||
}
|
||||
|
||||
removeConnectionTypes(connection, removeMassTypes);
|
||||
addConnectionTypes(connection, addMassType);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get some scope info for a given info string
|
||||
* @param {string} info
|
||||
@@ -1430,8 +1445,9 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set default map Options (
|
||||
* -> HINT: This function triggers Events! Promise is resolved before trigger completed
|
||||
* Set default map options (from right menu)
|
||||
* This function is called only ONCE per map after create!
|
||||
* -> HINT: This function triggers events! Promise is resolved before trigger callback finishes
|
||||
* @param mapElement
|
||||
* @param mapConfig
|
||||
* @returns {Promise<any>}
|
||||
@@ -1464,8 +1480,10 @@ define([
|
||||
|
||||
// init endpoint overlay --------------------------------------------------------------------------
|
||||
mapElement.triggerMenuEvent('MapOption', {
|
||||
option: 'mapEndpoint',
|
||||
toggle: false
|
||||
option: 'mapSignatureOverlays',
|
||||
toggle: false,
|
||||
skipOnEnable: true, // skip callback -> Otherwise it would run 2 times on map create
|
||||
skipOnDisable: true // skip callback -> Otherwise it would run 2 times on map create
|
||||
});
|
||||
|
||||
resolve({
|
||||
@@ -1494,30 +1512,61 @@ define([
|
||||
|
||||
/**
|
||||
* scroll map to default (stored) x/y coordinates
|
||||
* @param mapElement
|
||||
* @param map
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let scrollToDefaultPosition = (mapElement) => {
|
||||
let scrollToDefaultPosition = map => {
|
||||
|
||||
let scrollToDefaultPositionExecutor = (resolve, reject) => {
|
||||
let mapWrapper = mapElement.parents('.' + config.mapWrapperClass);
|
||||
let scrollToDefaultPositionExecutor = resolve => {
|
||||
let payload = {
|
||||
action: 'scrollToDefaultPosition',
|
||||
data: false
|
||||
};
|
||||
|
||||
// auto scroll map to previous stored position
|
||||
// no map scroll on zoomed maps -> scrollbar offset on zoomed maps does not work properly
|
||||
// -> implementation would be difficult...
|
||||
if(map.getZoom() === 1){
|
||||
let mapElement = $(map.getContainer());
|
||||
let promiseStore = getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(data => {
|
||||
if(data && data.scrollOffset){
|
||||
let mapWrapper = mapElement.parents('.' + config.mapWrapperClass);
|
||||
Scrollbar.scrollToPosition(mapWrapper, [data.scrollOffset.y, data.scrollOffset.x]);
|
||||
}
|
||||
|
||||
resolve(payload);
|
||||
});
|
||||
}else{
|
||||
resolve(payload);
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(scrollToDefaultPositionExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* zoom map to default (stored) scale()
|
||||
* @param map
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let zoomToDefaultScale = map => {
|
||||
|
||||
let zoomToDefaultScaleExecutor = resolve => {
|
||||
let mapElement = $(map.getContainer());
|
||||
let promiseStore = getLocaleData('map', mapElement.data('id'));
|
||||
promiseStore.then(data => {
|
||||
// This code runs once the value has been loaded from offline storage
|
||||
if(data && data.scrollOffset){
|
||||
Scrollbar.scrollToPosition(mapWrapper, [data.scrollOffset.y, data.scrollOffset.x]);
|
||||
if(data && data.mapZoom){
|
||||
setZoom(map, data.mapZoom);
|
||||
}
|
||||
|
||||
resolve({
|
||||
action: 'scrollToDefaultPosition',
|
||||
action: 'zoomToDefaultScale',
|
||||
data: false
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(scrollToDefaultPositionExecutor);
|
||||
return new Promise(zoomToDefaultScaleExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1825,13 +1874,12 @@ define([
|
||||
|
||||
let title = tooltipData.name;
|
||||
|
||||
if(tooltipData.size){
|
||||
title += ' <kbd>' + tooltipData.size.label + '</kbd>';
|
||||
}
|
||||
|
||||
if(tooltipData.security){
|
||||
// K162 has no security
|
||||
|
||||
if(!tooltipData.class){
|
||||
tooltipData.class = Util.getSecurityClassForSystem(tooltipData.security);
|
||||
}
|
||||
|
||||
title += '<span class="pull-right ' + tooltipData.class +'">' + tooltipData.security + '</span>';
|
||||
}
|
||||
|
||||
@@ -1961,7 +2009,6 @@ define([
|
||||
|
||||
return {
|
||||
config: config,
|
||||
mapOptions: mapOptions,
|
||||
setMapInstance: setMapInstance,
|
||||
getMapInstance: getMapInstance,
|
||||
existsMapInstance: existsMapInstance,
|
||||
@@ -1996,6 +2043,7 @@ define([
|
||||
checkForConnection: checkForConnection,
|
||||
getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope,
|
||||
setConnectionWHStatus: setConnectionWHStatus,
|
||||
setConnectionJumpMassType: setConnectionJumpMassType,
|
||||
getScopeInfoForConnection: getScopeInfoForConnection,
|
||||
getDataByConnections: getDataByConnections,
|
||||
deleteConnections: deleteConnections,
|
||||
@@ -2016,6 +2064,7 @@ define([
|
||||
setMapDefaultOptions: setMapDefaultOptions,
|
||||
getSystemPosition: getSystemPosition,
|
||||
scrollToDefaultPosition: scrollToDefaultPosition,
|
||||
zoomToDefaultScale: zoomToDefaultScale,
|
||||
getSystemId: getSystemId,
|
||||
checkRight: checkRight,
|
||||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||||
|
||||
@@ -121,6 +121,25 @@ define([
|
||||
*/
|
||||
let initData = () => {
|
||||
|
||||
/**
|
||||
* add wormhole size data for each wormhole
|
||||
* @param wormholes
|
||||
* @returns {*}
|
||||
*/
|
||||
let addWormholeSizeData = wormholes => {
|
||||
for(let [wormholeName, wormholeData] of Object.entries(wormholes)){
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
|
||||
for(let [sizeName, sizeData] of Object.entries(Init.wormholeSizes)){
|
||||
if(wormholeData.massIndividual >= sizeData.jumpMassMin){
|
||||
wormholeData.size = sizeData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return wormholes;
|
||||
};
|
||||
|
||||
let initDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.initData).done(response => {
|
||||
if( response.error.length > 0 ){
|
||||
@@ -139,7 +158,7 @@ define([
|
||||
Init.connectionScopes = response.connectionScopes;
|
||||
Init.systemStatus = response.systemStatus;
|
||||
Init.systemType = response.systemType;
|
||||
Init.wormholes = response.wormholes;
|
||||
Init.wormholes = addWormholeSizeData(response.wormholes);
|
||||
Init.characterStatus = response.characterStatus;
|
||||
Init.routes = response.routes;
|
||||
Init.url = response.url;
|
||||
|
||||
@@ -220,17 +220,7 @@ define([
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Effect info'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-crosshairs fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSystemEffectInfo');
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Jump info'
|
||||
html: ' Wormhole data'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-space-shuttle fa-fw'
|
||||
@@ -238,6 +228,16 @@ define([
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowJumpInfo');
|
||||
}),
|
||||
$('<a>', {
|
||||
class: 'list-group-item list-group-item-info',
|
||||
html: ' Wormhole effects'
|
||||
}).prepend(
|
||||
$('<i>',{
|
||||
class: 'fas fa-crosshairs fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSystemEffectInfo');
|
||||
}),
|
||||
getMenuHeadline('Settings'),
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
@@ -379,7 +379,7 @@ define([
|
||||
})
|
||||
).on('click', function(){
|
||||
Util.getMapModule().getActiveMap().triggerMenuEvent('MapOption', {
|
||||
option: 'mapEndpoint',
|
||||
option: 'mapSignatureOverlays',
|
||||
toggle: true
|
||||
});
|
||||
}),
|
||||
|
||||
@@ -26,13 +26,6 @@ define([
|
||||
let data = {
|
||||
config: config,
|
||||
wormholes: Object.keys(Init.wormholes).map(function(k){ return Init.wormholes[k]; }), // convert Json to array
|
||||
securityClass: function(){
|
||||
return function(value, render){
|
||||
return this.Util.getSecurityClassForSystem( render(value) );
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
}),
|
||||
massValue: function(){
|
||||
return function(value, render){
|
||||
let mass = render(value);
|
||||
|
||||
@@ -382,9 +382,7 @@ define([
|
||||
let statics = [];
|
||||
for(let wormholeName of cellData){
|
||||
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
let security = wormholeData.security;
|
||||
let secClass = Util.getSecurityClassForSystem(security);
|
||||
statics.push('<span class="' + secClass + '">' + security + '</span>');
|
||||
statics.push('<span class="' + wormholeData.class + '">' + wormholeData.security + '</span>');
|
||||
}
|
||||
return statics.join(' ');
|
||||
}
|
||||
@@ -596,7 +594,7 @@ define([
|
||||
display: (cellData, type, rowData, meta) => {
|
||||
let connectionClasses = MapUtil.getConnectionFakeClassesByTypes(cellData);
|
||||
connectionClasses = connectionClasses.join(' ');
|
||||
return '<div class="pf-fake-connection ' + connectionClasses + '"></div>';
|
||||
return '<div class="' + connectionClasses + '"></div>';
|
||||
}
|
||||
}
|
||||
},{
|
||||
|
||||
@@ -57,7 +57,7 @@ define([
|
||||
|
||||
for(let [areaId, areaData] of Object.entries(effectData)){
|
||||
let systemType = 'C' + areaId;
|
||||
let securityClass = Util.getSecurityClassForSystem( systemType );
|
||||
let securityClass = Util.getSecurityClassForSystem(systemType);
|
||||
|
||||
if(areaId === '1'){
|
||||
rows.push( $('<tr>') );
|
||||
|
||||
@@ -166,7 +166,7 @@ define([
|
||||
if(type.includes('wh_critical')){
|
||||
styleClass.push('pf-wh-critical');
|
||||
}
|
||||
if(type.includes('frigate')){
|
||||
if(type.includes('wh_jump_mass_s')){
|
||||
styleClass.push('pf-wh-frig');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,22 +306,22 @@ define([
|
||||
let connection = $().getConnectionById(data.mapId, data.connectionId);
|
||||
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sourceLabel = signatureTypeNames.source.labels;
|
||||
let targetLabel = signatureTypeNames.target.labels;
|
||||
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabel.join(', ')));
|
||||
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabel.join(', ')));
|
||||
let sourceLabels = signatureTypeNames.source.labels;
|
||||
let targetLabels = signatureTypeNames.target.labels;
|
||||
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabels));
|
||||
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabels));
|
||||
|
||||
// remove K162
|
||||
sourceLabel = sourceLabel.diff(['K162']);
|
||||
targetLabel = targetLabel.diff(['K162']);
|
||||
sourceLabels = sourceLabels.diff(['K162']);
|
||||
targetLabels = targetLabels.diff(['K162']);
|
||||
|
||||
// get static wormhole data by endpoint Labels
|
||||
let wormholeName = '';
|
||||
let wormholeData = null;
|
||||
if(sourceLabel.length === 1 && targetLabel.length === 0){
|
||||
wormholeName = sourceLabel[0];
|
||||
}else if(sourceLabel.length === 0 && targetLabel.length === 1){
|
||||
wormholeName = targetLabel[0];
|
||||
if(sourceLabels.length === 1 && targetLabels.length === 0){
|
||||
wormholeName = sourceLabels[0];
|
||||
}else if(sourceLabels.length === 0 && targetLabels.length === 1){
|
||||
wormholeName = targetLabels[0];
|
||||
}
|
||||
|
||||
if(
|
||||
@@ -329,7 +329,6 @@ define([
|
||||
Init.wormholes.hasOwnProperty(wormholeName)
|
||||
){
|
||||
wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
|
||||
// init wormhole tooltip ----------------------------------------------
|
||||
let massTotalTooltipCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalTooltipClass);
|
||||
|
||||
@@ -143,7 +143,6 @@ define([
|
||||
){
|
||||
for(let wormholeName of systemData.statics){
|
||||
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
|
||||
staticsData.push(wormholeData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +970,16 @@ define([
|
||||
return this.filter(function(i){return a.indexOf(i) < 0;});
|
||||
};
|
||||
|
||||
/**
|
||||
* compares two arrays if all elements in a are also in b
|
||||
* element order is ignored
|
||||
* @param a
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Array.prototype.equalValues = function(a){
|
||||
return this.diff(a).concat(a.diff(this)).length === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* sort array of objects by property name
|
||||
* @param p
|
||||
|
||||
@@ -1,350 +0,0 @@
|
||||
;(function() {
|
||||
|
||||
var root = this;
|
||||
var Farahey;
|
||||
if (typeof exports !== 'undefined') {
|
||||
Farahey = exports;
|
||||
} else {
|
||||
Farahey = root.Farahey = {};
|
||||
}
|
||||
|
||||
var findInsertionPoint = function(sortedArr, val, comparator) {
|
||||
var low = 0, high = sortedArr.length;
|
||||
var mid = -1, c = 0;
|
||||
while(low < high) {
|
||||
mid = parseInt((low + high)/2);
|
||||
c = comparator(sortedArr[mid], val);
|
||||
if(c < 0) {
|
||||
low = mid + 1;
|
||||
}else if(c > 0) {
|
||||
high = mid;
|
||||
}else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
},
|
||||
geomSupport = typeof jsPlumbGeom !== "undefined" ? jsPlumbGeom : Biltong,
|
||||
insertSorted = function(array, value, comparator) {
|
||||
var ip = findInsertionPoint(array, value, comparator);
|
||||
array.splice(ip, 0, value);
|
||||
},
|
||||
distanceFromOriginComparator = function(r1, r2, origin) {
|
||||
var d1 = geomSupport.lineLength(origin, [ r1.x + (r1.w / 2), r1.y + (r1.h / 2)]),
|
||||
d2 = geomSupport.lineLength(origin, [ r2.x + (r2.w / 2), r2.y + (r2.h / 2)]);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
},
|
||||
EntryComparator = function(origin, getSize) {
|
||||
var _origin = origin,
|
||||
_cache = {},
|
||||
_get = function(entry) {
|
||||
if (!_cache[entry[1]]) {
|
||||
var s = getSize(entry[2]);
|
||||
_cache[entry[1]] = {
|
||||
l:entry[0][0],
|
||||
t:entry[0][1],
|
||||
w:s[0],
|
||||
h:s[1],
|
||||
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
|
||||
};
|
||||
}
|
||||
return _cache[entry[1]];
|
||||
}
|
||||
this.setOrigin = function(o) {
|
||||
_origin = o;
|
||||
_cache = {};
|
||||
};
|
||||
this.compare = function(e1, e2) {
|
||||
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
|
||||
d2 = geomSupport.lineLength(_origin, _get(e2).center);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
|
||||
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
|
||||
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
|
||||
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
|
||||
_genAdj = function(r1, r2, m, b, s) {
|
||||
if (isNaN(m)) m = 0;
|
||||
var y = r2.y + r2.h,
|
||||
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
|
||||
theta = Math.atan(m);
|
||||
|
||||
if (_isOnEdge(r2, "x", "w", x)) {
|
||||
var rise = _adj[s][1](r1, r2),
|
||||
hyp = rise / Math.sin(theta),
|
||||
run = hyp * Math.cos(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
else {
|
||||
var run = _adj[s][0](r1, r2),
|
||||
hyp = run / Math.cos(theta),
|
||||
rise = hyp * Math.sin(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
},
|
||||
/*
|
||||
* Calculates how far to move r2 from r1 so that it no longer overlaps.
|
||||
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
|
||||
* otherwise we want it to move along a vector joining the two rectangle centers.
|
||||
*/
|
||||
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
|
||||
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
|
||||
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
|
||||
m = geomSupport.gradient(c1, c2),
|
||||
s = geomSupport.quadrant(c1, c2),
|
||||
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
|
||||
|
||||
return _genAdj(r1, r2, m, b, s);
|
||||
},
|
||||
// calculate a padded rectangle for the given element with offset & size, and desired padding.
|
||||
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
|
||||
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
|
||||
},
|
||||
_magnetize = function(positionArray, positions, sizes, padding,
|
||||
constrain, origin, filter,
|
||||
updateOnStep, stepInterval, stepCallback)
|
||||
{
|
||||
origin = origin || [0,0];
|
||||
stepCallback = stepCallback || function() { };
|
||||
|
||||
var focus = _paddedRectangle(origin, [1,1], padding),
|
||||
iterations = 100, iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
|
||||
_movedElements = {},
|
||||
_move = function(id, o, x, y) {
|
||||
_movedElements[id] = true;
|
||||
o[0] += x;
|
||||
o[1] += y;
|
||||
},
|
||||
step = function() {
|
||||
for (var i = 0; i < positionArray.length; i++) {
|
||||
var o1 = positions[positionArray[i][1]],
|
||||
oid = positionArray[i][1],
|
||||
a1 = positionArray[i][2], // angle to node from magnet origin
|
||||
s1 = sizes[positionArray[i][1]],
|
||||
// create a rectangle for first element: this encompasses the element and padding on each
|
||||
//side
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
|
||||
if (filter(positionArray[i][1]) && geomSupport.intersects(focus, r1)) {
|
||||
adjustBy = _calculateSpacingAdjustment(focus, r1);
|
||||
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
|
||||
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
|
||||
// now move others to account for this one, if necessary.
|
||||
// reset rectangle for node
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
for (var j = 0; j < positionArray.length; j++) {
|
||||
if (i != j) {
|
||||
var o2 = positions[positionArray[j][1]],
|
||||
a2 = positionArray[j][2], // angle to node from magnet origin
|
||||
s2 = sizes[positionArray[j][1]],
|
||||
// create a rectangle for the second element, again by putting padding of the desired
|
||||
// amount around the bounds of the element.
|
||||
r2 = _paddedRectangle(o2, s2, padding);
|
||||
|
||||
// if the two rectangles intersect then figure out how much to move the second one by.
|
||||
if (geomSupport.intersects(r1, r2)) {
|
||||
// TODO in 0.3, instead of moving neither, the other node should move.
|
||||
if (filter(positionArray[j][1])) {
|
||||
uncleanRun = true;
|
||||
adjustBy = _calculateSpacingAdjustment(r1, r2),
|
||||
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
|
||||
|
||||
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateOnStep)
|
||||
stepCallback();
|
||||
|
||||
if (uncleanRun && iteration < iterations) {
|
||||
uncleanRun = false;
|
||||
iteration++;
|
||||
if (updateOnStep) {
|
||||
window.setTimeout(step, stepInterval);
|
||||
}
|
||||
else
|
||||
step();
|
||||
}
|
||||
};
|
||||
|
||||
step();
|
||||
return _movedElements;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @name Magnetizer
|
||||
* @classdesc Applies repulsive magnetism to a set of elements relative to a given point, with a specified
|
||||
* amount of padding around the point.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Magnetizer#constructor
|
||||
* @function
|
||||
* @param {Selector|Element} [container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} getPosition A function that takes an element id and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} setPosition A function that takes an element id and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} getSize A function that takes an element id and returns its size, in pixels.
|
||||
* @param {Integer[]} [padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Integer[]} [origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} elements List of elements on which to operate.
|
||||
* @param {Boolean} [executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
root.Magnetizer = function(params) {
|
||||
var getPosition = params.getPosition,
|
||||
getSize = params.getSize,
|
||||
getId = params.getId,
|
||||
setPosition = params.setPosition,
|
||||
padding = params.padding || [20, 20],
|
||||
// expects a { left:.., top:... } object. returns how far it can actually go.
|
||||
constrain = params.constrain || function(id, current, delta) { return delta; },
|
||||
positionArray = [],
|
||||
positions = {},
|
||||
sizes = {},
|
||||
elements = params.elements || [],
|
||||
origin = params.origin || [0,0],
|
||||
executeNow = params.executeNow,
|
||||
minx, miny, maxx, maxy,
|
||||
getOrigin = this.getOrigin = function() { return origin; },
|
||||
filter = params.filter || function(_) { return true; },
|
||||
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
|
||||
comparator = new EntryComparator(origin, getSize),
|
||||
updateOnStep = params.updateOnStep,
|
||||
stepInterval = params.stepInterval || 350,
|
||||
originDebugMarker,
|
||||
debug = params.debug,
|
||||
createOriginDebugger = function() {
|
||||
var d = document.createElement("div");
|
||||
d.style.position = "absolute";
|
||||
d.style.width = "10px";
|
||||
d.style.height = "10px";
|
||||
d.style.backgroundColor = "red";
|
||||
document.body.appendChild(d);
|
||||
originDebugMarker = d;
|
||||
},
|
||||
_addToPositionArray = function(p) {
|
||||
if (!orderByDistanceFromOrigin || positionArray.length == 0)
|
||||
positionArray.push(p);
|
||||
else {
|
||||
insertSorted(positionArray, p, comparator.compare);
|
||||
}
|
||||
},
|
||||
_updatePositions = function() {
|
||||
comparator.setOrigin(origin);
|
||||
positionArray = []; positions = {}; sizes = {};
|
||||
minx = miny = Infinity;
|
||||
maxx = maxy = -Infinity;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var p = getPosition(elements[i]),
|
||||
s = getSize(elements[i]),
|
||||
id = getId(elements[i]);
|
||||
|
||||
positions[id] = [p.left, p.top];
|
||||
_addToPositionArray([ [p.left, p.top], id, elements[i]]);
|
||||
sizes[id] = s;
|
||||
minx = Math.min(minx, p.left);
|
||||
miny = Math.min(miny, p.top);
|
||||
maxx = Math.max(maxx, p.left + s[0]);
|
||||
maxy = Math.max(maxy, p.top + s[1]);
|
||||
}
|
||||
},
|
||||
_run = function() {
|
||||
if (elements.length > 1) {
|
||||
var _movedElements = _magnetize(positionArray, positions, sizes, padding, constrain, origin, filter, updateOnStep, stepInterval, _positionElements);
|
||||
_positionElements(_movedElements);
|
||||
}
|
||||
},
|
||||
_positionElements = function(_movedElements) {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var id = getId(elements[i]);
|
||||
if (_movedElements[id])
|
||||
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
|
||||
}
|
||||
},
|
||||
setOrigin = function(o) {
|
||||
if (o != null) {
|
||||
origin = o;
|
||||
comparator.setOrigin(o);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#execute
|
||||
* @function
|
||||
* @desc Runs the magnetize routine.
|
||||
* @param {Integer[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
|
||||
*/
|
||||
this.execute = function(o) {
|
||||
setOrigin(o);
|
||||
_updatePositions();
|
||||
_run();
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#executeAtCenter
|
||||
* @function
|
||||
* @desc Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
|
||||
*/
|
||||
this.executeAtCenter = function() {
|
||||
_updatePositions();
|
||||
setOrigin([
|
||||
(minx + maxx) / 2,
|
||||
(miny + maxy) / 2
|
||||
]);
|
||||
_run();
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetizer#executeAtEvent
|
||||
* @function
|
||||
* @desc Runs the magnetize routine using the location of the given event as the origin. To use this
|
||||
* method you need to have provided a `container`, and a `getContainerPosition` function to the
|
||||
* constructor.
|
||||
* @param {Event} e Event to get origin location from.
|
||||
*/
|
||||
this.executeAtEvent = function(e) {
|
||||
var c = params.container,
|
||||
o = params.getContainerPosition(c),
|
||||
x = e.pageX - o.left + c[0].scrollLeft,
|
||||
y = e.pageY - o.top + c[0].scrollTop;
|
||||
|
||||
if (debug) {
|
||||
originDebugMarker.style.left = e.pageX + "px";
|
||||
originDebugMarker.style.top = e.pageY + "px";
|
||||
}
|
||||
|
||||
this.execute([x,y]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Magnetize#setElements
|
||||
* @function
|
||||
* @desc Sets the current list of elements.
|
||||
* @param {Object[]} _els List of elements, in whatever format the magnetizer is setup to use.
|
||||
*/
|
||||
this.setElements = function(_els) {
|
||||
elements = _els;
|
||||
};
|
||||
|
||||
|
||||
if (debug)
|
||||
createOriginDebugger();
|
||||
|
||||
if (executeNow) this.execute();
|
||||
|
||||
};
|
||||
}).call(this);
|
||||
|
||||
518
public/js/v1.5.2/lib/farahey.js
Normal file
518
public/js/v1.5.2/lib/farahey.js
Normal file
@@ -0,0 +1,518 @@
|
||||
;(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
var root = this;
|
||||
var Farahey = root.Farahey = {};
|
||||
if (typeof exports !== 'undefined') {
|
||||
exports.Farahey = Farahey;
|
||||
}
|
||||
|
||||
var findInsertionPoint = function(sortedArr, val, comparator) {
|
||||
var low = 0, high = sortedArr.length;
|
||||
var mid = -1, c = 0;
|
||||
while(low < high) {
|
||||
mid = parseInt((low + high)/2);
|
||||
c = comparator(sortedArr[mid], val);
|
||||
if(c < 0) {
|
||||
low = mid + 1;
|
||||
}else if(c > 0) {
|
||||
high = mid;
|
||||
}else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
},
|
||||
geomSupport = root.Biltong,
|
||||
insertSorted = function(array, value, comparator) {
|
||||
var ip = findInsertionPoint(array, value, comparator);
|
||||
array.splice(ip, 0, value);
|
||||
},
|
||||
EntryComparator = function(origin, getSize) {
|
||||
var _origin = origin,
|
||||
_cache = {},
|
||||
_get = function(entry) {
|
||||
if (!_cache[entry[1]]) {
|
||||
var s = getSize(entry[2]);
|
||||
_cache[entry[1]] = {
|
||||
l:entry[0][0],
|
||||
t:entry[0][1],
|
||||
w:s[0],
|
||||
h:s[1],
|
||||
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
|
||||
};
|
||||
}
|
||||
return _cache[entry[1]];
|
||||
};
|
||||
|
||||
this.setOrigin = function(o) {
|
||||
_origin = o;
|
||||
_cache = {};
|
||||
};
|
||||
this.compare = function(e1, e2) {
|
||||
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
|
||||
d2 = geomSupport.lineLength(_origin, _get(e2).center);
|
||||
|
||||
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
|
||||
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
|
||||
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
|
||||
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
|
||||
_genAdj = function(r1, r2, m, b, s) {
|
||||
if (isNaN(m)) m = 0;
|
||||
var y = r2.y + r2.h,
|
||||
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
|
||||
theta = Math.atan(m),
|
||||
rise, hyp, run;
|
||||
|
||||
if (_isOnEdge(r2, "x", "w", x)) {
|
||||
rise = _adj[s][1](r1, r2);
|
||||
hyp = rise / Math.sin(theta);
|
||||
run = hyp * Math.cos(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
else {
|
||||
run = _adj[s][0](r1, r2);
|
||||
hyp = run / Math.cos(theta);
|
||||
rise = hyp * Math.sin(theta);
|
||||
return { left:run, top:rise };
|
||||
}
|
||||
},
|
||||
/*
|
||||
* Calculates how far to move r2 from r1 so that it no longer overlaps.
|
||||
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
|
||||
* otherwise we want it to move along a vector joining the two rectangle centers.
|
||||
*/
|
||||
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
|
||||
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
|
||||
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
|
||||
m = geomSupport.gradient(c1, c2),
|
||||
s = geomSupport.quadrant(c1, c2),
|
||||
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
|
||||
|
||||
return _genAdj(r1, r2, m, b, s);
|
||||
},
|
||||
// calculate a padded rectangle for the given element with offset & size, and desired padding.
|
||||
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
|
||||
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
|
||||
},
|
||||
_magnetize = function(positionArray, positions, sizes, padding,
|
||||
constrain, origin, filter,
|
||||
updateOnStep, stepInterval, stepCallback, iterations,
|
||||
exclude, excludeFocus)
|
||||
{
|
||||
origin = origin || [0,0];
|
||||
stepCallback = stepCallback || function() { };
|
||||
iterations = iterations || 2;
|
||||
|
||||
var focus = _paddedRectangle(origin, [1,1], padding),
|
||||
iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
|
||||
_movedElements = {},
|
||||
_move = function(id, o, x, y) {
|
||||
_movedElements[id] = true;
|
||||
o[0] += x;
|
||||
o[1] += y;
|
||||
},
|
||||
step = function() {
|
||||
for (var i = 0; i < positionArray.length; i++) {
|
||||
|
||||
if (exclude(positionArray[i][1], positionArray[i][2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var o1 = positions[positionArray[i][1]],
|
||||
oid = positionArray[i][1],
|
||||
a1 = positionArray[i][2], // angle to node from magnet origin
|
||||
s1 = sizes[positionArray[i][1]],
|
||||
// create a rectangle for first element: this encompasses the element and padding on each
|
||||
//side
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
|
||||
if (!excludeFocus && filter(positionArray[i][1], positionArray[i][2]) && geomSupport.intersects(focus, r1)) {
|
||||
adjustBy = _calculateSpacingAdjustment(focus, r1);
|
||||
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
|
||||
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
|
||||
// now move others to account for this one, if necessary.
|
||||
// reset rectangle for node
|
||||
r1 = _paddedRectangle(o1, s1, padding);
|
||||
for (var j = 0; j < positionArray.length; j++) {
|
||||
if (i != j) {
|
||||
|
||||
if (exclude(positionArray[j][1], positionArray[j][2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter(positionArray[j][1], positionArray[j][2])) {
|
||||
var o2 = positions[positionArray[j][1]],
|
||||
s2 = sizes[positionArray[j][1]],
|
||||
// create a rectangle for the second element, again by putting padding of the desired
|
||||
// amount around the bounds of the element.
|
||||
r2 = _paddedRectangle(o2, s2, padding);
|
||||
|
||||
// if the two rectangles intersect then figure out how much to move the second one by.
|
||||
if (geomSupport.intersects(r1, r2)) {
|
||||
// TODO (?), instead of moving neither, the other node should move.
|
||||
uncleanRun = true;
|
||||
adjustBy = _calculateSpacingAdjustment(r1, r2);
|
||||
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
|
||||
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateOnStep)
|
||||
stepCallback();
|
||||
|
||||
if (uncleanRun && iteration < iterations) {
|
||||
uncleanRun = false;
|
||||
iteration++;
|
||||
if (updateOnStep) {
|
||||
window.setTimeout(step, stepInterval);
|
||||
}
|
||||
else
|
||||
step();
|
||||
}
|
||||
};
|
||||
|
||||
step();
|
||||
return _movedElements;
|
||||
};
|
||||
|
||||
var _convertElements = function(l) {
|
||||
if (l == null) return null;
|
||||
else if (Object.prototype.toString.call(l) === "[object Array]") {
|
||||
var a = [];
|
||||
a.push.apply(a, l);
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
var o = [];
|
||||
for (var i in l) o.push(l[i]);
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies repulsive magnetism to a set of elements relative to a given point, with a specified
|
||||
* amount of padding around the point.
|
||||
* @class FaraheyInstance
|
||||
* @constructor
|
||||
* @param {Object} params Constructor parameters.
|
||||
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
|
||||
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
|
||||
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
var FaraheyInstance = function(params) {
|
||||
var getPosition = params.getPosition,
|
||||
getSize = params.getSize,
|
||||
getId = params.getId,
|
||||
setPosition = params.setPosition,
|
||||
padding = params.padding || [20, 20],
|
||||
// expects a { left:.., top:... } object. returns how far it can actually go.
|
||||
constrain = params.constrain || function(id, current, delta) { return delta; },
|
||||
positionArray = [],
|
||||
positions = {},
|
||||
sizes = {},
|
||||
elements = _convertElements(params.elements || []),
|
||||
origin = params.origin || [0,0],
|
||||
executeNow = params.executeNow,
|
||||
//minx, miny, maxx, maxy,
|
||||
getOrigin = this.getOrigin = function() { return origin; },
|
||||
filter = params.filter || function(_) { return true; },
|
||||
exclude = params.exclude || function(_) { return false;},
|
||||
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
|
||||
comparator = new EntryComparator(origin, getSize),
|
||||
updateOnStep = params.updateOnStep,
|
||||
stepInterval = params.stepInterval || 350,
|
||||
originDebugMarker,
|
||||
debug = params.debug,
|
||||
createOriginDebugger = function() {
|
||||
var d = document.createElement("div");
|
||||
d.style.position = "absolute";
|
||||
d.style.width = "10px";
|
||||
d.style.height = "10px";
|
||||
d.style.backgroundColor = "red";
|
||||
document.body.appendChild(d);
|
||||
originDebugMarker = d;
|
||||
},
|
||||
_addToPositionArray = function(p) {
|
||||
if (!orderByDistanceFromOrigin || positionArray.length == 0)
|
||||
positionArray.push(p);
|
||||
else {
|
||||
insertSorted(positionArray, p, comparator.compare);
|
||||
}
|
||||
},
|
||||
_computeExtents = function(els) {
|
||||
var minx, miny, maxx, maxy;
|
||||
minx = miny = Infinity;
|
||||
maxx = maxy = -Infinity;
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
var p = getPosition(els[i]),
|
||||
s = getSize(els[i]),
|
||||
id = getId(els[i]);
|
||||
|
||||
positions[id] = [p.left, p.top];
|
||||
_addToPositionArray([ [p.left, p.top], id, els[i]]);
|
||||
sizes[id] = s;
|
||||
minx = Math.min(minx, p.left);
|
||||
miny = Math.min(miny, p.top);
|
||||
maxx = Math.max(maxx, p.left + s[0]);
|
||||
maxy = Math.max(maxy, p.top + s[1]);
|
||||
}
|
||||
|
||||
return [ minx, maxx, miny, maxy ];
|
||||
|
||||
},
|
||||
_updatePositions = function() {
|
||||
comparator.setOrigin(origin);
|
||||
positionArray = []; positions = {}; sizes = {};
|
||||
return _computeExtents(elements);
|
||||
},
|
||||
_run = function(options) {
|
||||
if (elements.length > 1) {
|
||||
options = options || {};
|
||||
var f = options.filter || filter;
|
||||
var p = options.padding || padding;
|
||||
var i = options.iterations;
|
||||
var e = options.exclude || exclude;
|
||||
var ef = options.excludeFocus;
|
||||
var _movedElements = _magnetize(positionArray, positions, sizes, p, constrain, origin, f, updateOnStep, stepInterval, _positionElements, i, e, ef);
|
||||
_positionElements(_movedElements);
|
||||
}
|
||||
},
|
||||
_positionElements = function(_movedElements) {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var id = getId(elements[i]);
|
||||
if (_movedElements[id])
|
||||
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
|
||||
}
|
||||
},
|
||||
setOrigin = function(o) {
|
||||
if (o != null) {
|
||||
origin = o;
|
||||
comparator.setOrigin(o);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the magnetize routine.
|
||||
* @method execute
|
||||
* @param {Number[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.execute = function(o, options) {
|
||||
setOrigin(o);
|
||||
_updatePositions();
|
||||
_run(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
|
||||
* @method executeAtCenter
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.executeAtCenter = function(options) {
|
||||
var extents = _updatePositions();
|
||||
setOrigin([
|
||||
(extents[0] + extents[1]) / 2,
|
||||
(extents[2] + extents[3]) / 2
|
||||
]);
|
||||
_run(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the magnetize routine using the location of the given event as the origin. To use this
|
||||
* method you need to have provided a `container`, and a `getContainerPosition` function to the
|
||||
* constructor.
|
||||
* @method executeAtEvent
|
||||
* @param {Event} e Event to get origin location from.
|
||||
* @param {Function} [options] Options to override defaults.
|
||||
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
|
||||
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
|
||||
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
|
||||
* but the slower it runs. The default is 2.
|
||||
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
|
||||
* moves, nor has any bearing on the movement of other elements.
|
||||
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
|
||||
*/
|
||||
this.executeAtEvent = function(e, options) {
|
||||
var c = params.container,
|
||||
o = params.getContainerPosition(c),
|
||||
x = e.pageX - o.left + c.scrollLeft,
|
||||
y = e.pageY - o.top + c.scrollTop;
|
||||
|
||||
if (debug) {
|
||||
originDebugMarker.style.left = e.pageX + "px";
|
||||
originDebugMarker.style.top = e.pageY + "px";
|
||||
}
|
||||
|
||||
this.execute([x,y], options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current set of elements on which to operate.
|
||||
* @method setElements
|
||||
* @param {Object[]|Object} _els List, or object hash, of elements, in whatever format the Magnetizer is setup to use. If you supply an object hash then a list is generated from the hash's values (the keys are ignored).
|
||||
*/
|
||||
this.setElements = function(_els) {
|
||||
elements = _convertElements(_els);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given element to the set of elements on which to operate.
|
||||
* @method addElement
|
||||
* @param el {Object} Element to add.
|
||||
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
|
||||
* for a much faster call when there are lots of elements, just use it with care.
|
||||
*/
|
||||
this.addElement = function(el, doNotTestForDuplicates) {
|
||||
if (el != null && (doNotTestForDuplicates || elements.indexOf(el) === -1)) {
|
||||
elements.push(el);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given elements to the set of elements on which to operate.
|
||||
* @method addElements
|
||||
* @param els {Object[]} Elements to add.
|
||||
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
|
||||
* for a much faster call when there are lots of elements, just use it with care.
|
||||
*/
|
||||
this.addElements = function(els, doNotTestForDuplicates) {
|
||||
if (doNotTestForDuplicates) {
|
||||
Array.prototype.push.apply(elements, els);
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
this.addElement(els[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the list of elements currently being managed.
|
||||
* @method getElements
|
||||
*/
|
||||
this.getElements = function() {
|
||||
return elements;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given element from the set of elements on which to operate.
|
||||
* @method removeElement
|
||||
* @param el {Object} Element to remove.
|
||||
*/
|
||||
this.removeElement = function(el) {
|
||||
var idx = -1;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i] == el) {
|
||||
idx = i; break;
|
||||
}
|
||||
}
|
||||
if (idx != -1) elements.splice(idx, 1);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the padding to insert between magnetized elements.
|
||||
* @method setPadding
|
||||
* @param {Number[]} p Array of padding for each axis.
|
||||
*/
|
||||
this.setPadding = function(p) {
|
||||
padding = p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the function used to constrain the movement of some element that the magnetizer wishes to relocate.
|
||||
* The function is given an element ID and an array of [x,y] values, where each value indicates the proposed amount
|
||||
* of movement in the given axis. The function is expected to return an array of [x,y] that indicates the allowed
|
||||
* amount of movement in each axis.
|
||||
* @method setConstrain
|
||||
* @param {Function} c
|
||||
*/
|
||||
this.setConstrain = function(c) {
|
||||
constrain = c;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the function used to determine whether or not a given element should be considered during the magnetization process.
|
||||
* @method setFilter
|
||||
* @param {Function} f Filter function to use. Takes an element ID and returns whether or not that element can be moved.
|
||||
*/
|
||||
this.setFilter = function(f) {
|
||||
filter = f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the Farahey instance. Use this to avoid memory leaks.
|
||||
* @method reset
|
||||
*/
|
||||
this.reset = function() {
|
||||
elements.length = 0;
|
||||
};
|
||||
|
||||
if (debug)
|
||||
createOriginDebugger();
|
||||
|
||||
if (executeNow) this.execute();
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a new FaraheyInstance
|
||||
* @method
|
||||
* @param {Object} params Method parameters.
|
||||
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
|
||||
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
|
||||
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
|
||||
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
|
||||
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
|
||||
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
|
||||
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
|
||||
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
|
||||
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
|
||||
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
|
||||
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
|
||||
*/
|
||||
Farahey.getInstance = function(params) {
|
||||
return new FaraheyInstance(params);
|
||||
};
|
||||
|
||||
}).call(typeof window !== 'undefined' ? window : this);
|
||||
|
||||
@@ -67,8 +67,12 @@ $.fn.dragToSelect = function (conf) {
|
||||
onRefresh: function () {return true;}
|
||||
}, c);
|
||||
|
||||
var realParent = $(this);
|
||||
var parent = realParent;
|
||||
var realParent = $(this);
|
||||
var parent = realParent;
|
||||
|
||||
// container for lasso element
|
||||
// -> the only reason for NOT using the .pf-map is because of the zoom [scale()] feature or .pf-map
|
||||
var lassoContainer = realParent.parent();
|
||||
|
||||
var animationFrameId;
|
||||
var mouseIsDown = false;
|
||||
@@ -124,7 +128,7 @@ $.fn.dragToSelect = function (conf) {
|
||||
|
||||
// Create select box
|
||||
var selectBox = $('<div>')
|
||||
.appendTo(parent)
|
||||
.appendTo(lassoContainer)
|
||||
.attr('class', config.className)
|
||||
.css('position', 'absolute');
|
||||
|
||||
@@ -156,20 +160,6 @@ $.fn.dragToSelect = function (conf) {
|
||||
return refreshed;
|
||||
}
|
||||
|
||||
// get scroll position
|
||||
/*
|
||||
var leftScroll = 0;
|
||||
var topScroll = 0;
|
||||
|
||||
if(realParent.attr('data-scroll-left')){
|
||||
leftScroll = parseInt(realParent.attr('data-scroll-left'));
|
||||
}
|
||||
|
||||
if(realParent.attr('data-scroll-top')){
|
||||
topScroll = parseInt(realParent.attr('data-scroll-top'));
|
||||
}
|
||||
*/
|
||||
|
||||
var left = lastMousePosition.x - parentDim.left + parent[0].scrollLeft;
|
||||
var top = lastMousePosition.y - parentDim.top + parent[0].scrollTop;
|
||||
var tempWidth = selectBoxOrigin.left - left;
|
||||
@@ -220,30 +210,6 @@ $.fn.dragToSelect = function (conf) {
|
||||
}
|
||||
};
|
||||
|
||||
// Scrolls parent if needed
|
||||
var scrollPerhaps = function (e) {
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll down
|
||||
if ((e.pageY + config.scrollTH) > (parentDim.top + parentDim.height)) {
|
||||
parent[0].scrollTop += config.scrollTH;
|
||||
}
|
||||
// Scroll up
|
||||
if ((e.pageY - config.scrollTH) < parentDim.top) {
|
||||
parent[0].scrollTop -= config.scrollTH;
|
||||
}
|
||||
// Scroll right
|
||||
if ((e.pageX + config.scrollTH) > (parentDim.left + parentDim.width)) {
|
||||
parent[0].scrollLeft += config.scrollTH;
|
||||
}
|
||||
// Scroll left
|
||||
if ((e.pageX - config.scrollTH) < parentDim.left) {
|
||||
parent[0].scrollLeft -= config.scrollTH;
|
||||
}
|
||||
};
|
||||
|
||||
// Selects all the elements in the select box's range
|
||||
var selectElementsInRange = function () {
|
||||
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
<tr>
|
||||
<th class=""></th>
|
||||
<th class="text-center">Leads to</th>
|
||||
<th class="text-center pf-table-cell-10" title="is static"><i class="fas fa-thumbtack"></i></th>
|
||||
<th class="text-center">Size</th>
|
||||
<th class="text-center" title="is static"><i class="fas fa-thumbtack"></i></th>
|
||||
<th class="text-right">Mass total</th>
|
||||
<th class="text-right">Mass individual</th>
|
||||
<th class="text-right">Mass regeneration</th>
|
||||
<th class="text-right">Lifetime</th>
|
||||
<th class="text-right" title="lifetime"><i class="fas fa-hourglass-start"></i></th>
|
||||
<th class="text-right">Sig strength</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -16,7 +17,8 @@
|
||||
{{#wormholes}}
|
||||
<tr>
|
||||
<td>{{name}}</td>
|
||||
<td class="text-center {{#securityClass}}{{security}}{{/securityClass}}">{{security}}</td>
|
||||
<td class="text-center {{class}}">{{security}}</td>
|
||||
<td class="text-center {{#size}}{{size.class}}{{/size}}" data-order="{{size.jumpMassMin}}">{{#size}}{{size.label}}{{/size}}</td>
|
||||
<td class="text-center" data-order="{{static}}">{{#formatStatic}}{{static}}{{/formatStatic}}</td>
|
||||
<td class="text-right" data-order="{{massTotal}}">{{#massValue}}{{massTotal}}{{/massValue}}</td>
|
||||
<td class="text-right" data-order="{{massIndividual}}">{{#massValue}}{{massIndividual}}{{/massValue}}</td>
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
<tr>
|
||||
<td class="col-sm-2 text-center">k-space</td>
|
||||
<td></td>
|
||||
<td class="col-sm-3 text-right">security</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -210,7 +210,7 @@
|
||||
<tr>
|
||||
<td class="col-sm-2 text-center">w-space</td>
|
||||
<td></td>
|
||||
<td class="col-sm-3 text-right">security</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -237,7 +237,7 @@
|
||||
<tr>
|
||||
<td class="col-sm-2 text-center">w-space</td>
|
||||
<td></td>
|
||||
<td class="col-sm-3 text-right">security</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -393,42 +393,50 @@
|
||||
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> Wormhole<small> (Wormhole has not yet had its stability significantly disrupted)</small></li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-stargate"></div> Stargate<small> (Stargates are static <em>"K-space"</em> connections)</small></li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-jumpbridge"></div> Jumpbridge<small> (Jumpbridges are player build <em>"K-space"</em> connections)</small></li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-abyssal"></div> Abyssal<small> (abyssal zone entrance <em>"a-space"</em> connections)</small></li>
|
||||
<li><div class="pf-fake-connection"></div> Wormhole - <em>"k-space"</em> connections</li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-stargate"></div> Stargate - static <em>"k-space"</em> connections</li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-jumpbridge"></div> Jumpbridge - player build <em>"k-space"</em> connections</li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-abyssal"></div> Abyssal - PVE zone entrance <em>"a-space"</em> connections</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-status">Connection status</h4>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-status">Connection mass status</h4>
|
||||
<p>
|
||||
Wormholes will gain various statuses during its <em>"Lifetime"</em>.<br>
|
||||
In addition to this, connections can get custom statuses.<br>
|
||||
Wormholes go through various mass stages over lifetime.<br>
|
||||
To reflect the mass status on map, wormholes can be flagged.<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) <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) <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>
|
||||
<li><div class="pf-fake-connection"></div> fresh - <em>"… has not yet had its stability significantly disrupted"</em> (>50%)</li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-wh-reduced"></div> reduced - <em>"… had its stability reduced, but not to a critical degree"</em> (50% - 10%)</li>
|
||||
<li><div class="pf-fake-connection pf-map-connection-wh-critical"></div> critical - <em>"… is on the verge of collapse"</em> (<10%)</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>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-size">Connection ship size</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>.
|
||||
Wormhole connections have a "max jump mass". Ships whose total mass exceed this mass, can not go through the hole.<br>
|
||||
The size of a wormhole 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 class="fa-ul">
|
||||
<li><i class="fa-li fas fa-char pf-jump-mass-s" data-char-content="S"></i> Small - <em>"Only the smallest ships can pass through this wormhole"</em> (Frigates, Destroyers,…)</li>
|
||||
<li><i class="fa-li fas fa-char pf-jump-mass-m" data-char-content="M"></i> Medium - <em>"Up to medium size ships can pass through this wormhole"</em> (Nestors, BCs,…)</li>
|
||||
<li><i class="fa-li fas fa-char pf-jump-mass-l" data-char-content="L"></i> Large - <em>"Larger ships can pass through this wormhole"</em> (BSs, Orcas,…)</li>
|
||||
<li><i class="fa-li fas fa-char pf-jump-mass-xl" data-char-content="XL"></i> Capital - <em>"Very large ships can pass through this wormhole"</em> (FAXes, Dreads, Freighters,…)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-label">Connection lifetime</h4>
|
||||
<p>
|
||||
The lifetime information of a wormhole indicates roughly what kind of time is remaining on the wormhole before it dies of natural causes.<br>
|
||||
Wormholes set to "EOL" (End Of Lifetime) can automatically be removed from the map 4h later on (check map settings).<br>
|
||||
EOL status 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><div class="pf-fake-connection pf-map-connection-wh-eol"></div> EOL - <em>"Wormhole is reaching the end of its natural lifetime"</em> (less than 4 hours)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-contextmenu">Context menu (connection)</h4>
|
||||
@@ -436,32 +444,24 @@
|
||||
<kbd>right click</kbd> a connection on the map to open the context menu.
|
||||
</p>
|
||||
<ul class="list-unstyled well" style=" margin-left: 10px;">
|
||||
<li><i class="fas fa-plane fa-fw"></i> Toggles this connection as <em>"Frigate Hole"</em> <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-frig">more</a></small></li>
|
||||
<li><i class="fas fa-exclamation-triangle fa-fw"></i> Toggles this connection as <em>"Preserve Mass"</em> <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-mass">more</a></small></li>
|
||||
<li><i class="fas fa-crosshairs fa-fw"></i> Changes the scope of this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a></small></li>
|
||||
<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>
|
||||
<li><i class="fas fa-hourglass-end fa-fw"></i> Toggle "EOL" (End Of Lifetime). Less than 4 hours until collapse <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-frig">more</a></small></li>
|
||||
<li><i class="fas fa-exclamation-triangle fa-fw"></i> Toggle "Preserve Mass" for connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-mass">more</a></small></li>
|
||||
<li><i class="fas fa-reply fa-rotate-180 fa-fw"></i> Set "mass status". Total mass passed through ['fresh', 'reduced', 'critical'] <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-status">more</a></small></li>
|
||||
<li><i class="fas fa-reply fa-rotate-180 fa-fw"></i> Set "ship size" for connection (mass per jump) ['S', 'M', 'L', 'XL'] <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-size">more</a></small></li>
|
||||
<li><i class="fas fa-crosshairs fa-fw"></i> Changes connection scope ['wormhole', 'stargate', 'jumpbridge'] <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-scope">more</a></small></li>
|
||||
<li><i class="fas fa-unlink fa-fw"></i> Delete/detach this connection <small><a href="#" data-target="#pf-manual-scrollspy-anchor-connection-delete">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>.
|
||||
Wormholes can be labeled with a <span class="label label-danger"><i class="fas fa-exclamation-triangle"></i> save mass</span> flag.<br>
|
||||
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>.
|
||||
(e.g. <span class="pf-system-sec-highSec">H</span> security exits).
|
||||
</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>
|
||||
<h4 id="pf-manual-scrollspy-anchor-connection-delete"><i class="fas fa-unlink fa-fw"></i> Delete/detach connection</h4>
|
||||
<p>
|
||||
Connections can be detached by several ways.
|
||||
</p>
|
||||
@@ -472,9 +472,6 @@
|
||||
<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>
|
||||
@@ -514,9 +511,9 @@
|
||||
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 <30%)</small></li>
|
||||
<li><i class="fa-li fas fa-circle txt-color txt-color-warning"></i></span> bad scanned <small>(System scanned to <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>
|
||||
<li><i class="fa-li fas fa-circle txt-color txt-color-danger"></i> not scanned <small>(System scanned to <30%)</small></li>
|
||||
<li><i class="fa-li fas fa-circle txt-color txt-color-warning"></i> bad scanned <small>(System scanned to <100%)</small></li>
|
||||
<li><i class="fa-li fas fa-circle txt-color txt-color-success"></i> full scanned <small>(System scanned to 100%)</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
@@ -594,24 +591,50 @@
|
||||
</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>
|
||||
<h4><i class="fas fa-align-left fa-fw"></i> Routes</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>.
|
||||
The <em>"Route"</em> search module is available for any active system <small>(<a href="#" data-target="#pf-manual-scrollspy-anchor-system-active">more</a>)</small>.
|
||||
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>
|
||||
<table class="table table-condensed" style="font-size: 12px; width: 90%">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan="6"> <i class="fas fa-fw fa-char pf-system-sec-highSec" data-char-content="H"></i></td>
|
||||
<td colspan="4"> <i class="fas fa-fw fa-char pf-system-sec-lowSec" data-char-content="L"></i></td>
|
||||
<td colspan="2"> <i class="fas fa-fw fa-char pf-system-sec-nullSec" data-char-content="0.0"></i></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-1-0"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-9"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-8"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-7"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-6"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-5"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-4"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-3"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-2"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-1"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-0"></i></td>
|
||||
<td class="col-xs-1 text-center"><i class="fas fa-square pf-system-security-0-0"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-1-0">1-0</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-9">0.9</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-8">0.8</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-7">0.7</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-6">0.6</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-5">0.5</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-4">0.4</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-3">0.3</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-2">0.2</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-1">0.1</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-0">0.0</samp></td>
|
||||
<td class="col-xs-1 text-center"><samp class="pf-system-security-0-0">-1.0</samp></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<h4><i class="fas fa-chart-bar fa-fw"></i> Recent activity</h4><p>
|
||||
@@ -653,7 +676,7 @@
|
||||
Events that trigger desktop notification.
|
||||
</p>
|
||||
<ul>
|
||||
<li>New Rally point</span> <small>(<i class="fas fa-volume-up fa-fw"></i> <a href="#" data-target="#pf-manual-scrollspy-anchor-system-rally">more</a>)</small></li>
|
||||
<li>New Rally point <small>(<i class="fas fa-volume-up fa-fw"></i> <a href="#" data-target="#pf-manual-scrollspy-anchor-system-rally">more</a>)</small></li>
|
||||
</ul>
|
||||
|
||||
<hr class="pf-manual-scroll-break">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{{#subText}}
|
||||
<li data-action="{{subAction}}">
|
||||
<a href="#" tabindex="-1" data-action="{{subAction}}">
|
||||
<i class="fas {{#subIcon}}{{subIcon}}{{/subIcon}} {{#subIconClass}}{{subIconClass}}{{/subIconClass}} fa-fw"></i>
|
||||
<i class="fas {{#subIcon}}{{subIcon}}{{/subIcon}} {{#subIconClass}}{{subIconClass}}{{/subIconClass}} fa-fw" {{#subChar}}data-char-content="{{subChar}}"{{/subChar}}></i>
|
||||
{{subText}}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -989,6 +989,9 @@ input[type="email"]{
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-submenu.disabled>a:after {
|
||||
border-left-color: $gray-light;
|
||||
}
|
||||
|
||||
.dropdown-submenu.pull-left {
|
||||
float: none;
|
||||
|
||||
@@ -44,6 +44,14 @@ em{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.fa-char{
|
||||
&:before{
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: bold;
|
||||
content: attr(data-char-content);
|
||||
}
|
||||
}
|
||||
|
||||
.no-scroll{
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -651,7 +659,6 @@ table{
|
||||
//background:url("#{$base-url}/#{$body-background-image}") $body-background-color;
|
||||
background-color: $body-background-color;
|
||||
background-repeat: no-repeat;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.pf-menu{
|
||||
@@ -1202,6 +1209,23 @@ table{
|
||||
color: $planet-color-temperate;
|
||||
}
|
||||
|
||||
// connection size by jump mass ===================================================================
|
||||
.pf-jump-mass-xl{
|
||||
//color: $indigo;
|
||||
}
|
||||
|
||||
.pf-jump-mass-l{
|
||||
//color: $blue;
|
||||
}
|
||||
|
||||
.pf-jump-mass-m{
|
||||
//color: $yellow-dark;
|
||||
}
|
||||
|
||||
.pf-jump-mass-s{
|
||||
//color: $orange;
|
||||
}
|
||||
|
||||
// "fake connection" classes for the map manual
|
||||
.pf-fake-connection{
|
||||
box-sizing: content-box;
|
||||
@@ -1210,7 +1234,7 @@ table{
|
||||
height: 4px;
|
||||
border-top: 2px solid $gray-light;
|
||||
border-bottom: 2px solid $gray-light;
|
||||
background-color: #3c3f41;
|
||||
background-color: $gray;
|
||||
position: relative;
|
||||
font-size: 10px;
|
||||
font-family: $font-family-sans-serif;
|
||||
@@ -1256,35 +1280,66 @@ table{
|
||||
background-color: $red-darker;
|
||||
}
|
||||
|
||||
&.pf-map-connection-frig{
|
||||
border-style: dashed;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
&.pf-map-connection-wh-size-s,
|
||||
&.pf-map-connection-wh-size-m,
|
||||
&.pf-map-connection-wh-size-l,
|
||||
&.pf-map-connection-wh-size-xl,
|
||||
&.pf-map-connection-preserve-mass{
|
||||
&:after{
|
||||
content: '?';
|
||||
background-color: $gray;
|
||||
color: $gray-lighter;
|
||||
padding: 1px 2px;
|
||||
position: absolute;
|
||||
left: calc(50% - 7px);
|
||||
top: -5px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 11px;
|
||||
line-height: 12px;
|
||||
min-width: 14px;
|
||||
text-align: center;
|
||||
@include border-radius(3px);
|
||||
@include box-shadow(0 3px 6px rgba(0,0,0,.3));
|
||||
}
|
||||
}
|
||||
|
||||
&.pf-map-connection-wh-size-s{
|
||||
border-style: dotted;
|
||||
|
||||
&:after{
|
||||
content: 'frig';
|
||||
background-color: $orange;
|
||||
color: $gray-darkest;
|
||||
padding: 0px 3px;
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
top: -6px;
|
||||
font-family: $font-family-bold;
|
||||
@include border-radius(3px);
|
||||
content: 'S';
|
||||
}
|
||||
}
|
||||
|
||||
&.pf-map-connection-wh-size-m{
|
||||
border-style: dashed;
|
||||
|
||||
&:after{
|
||||
content: 'M';
|
||||
}
|
||||
}
|
||||
|
||||
&.pf-map-connection-wh-size-l{
|
||||
|
||||
&:after{
|
||||
content: 'L';
|
||||
}
|
||||
}
|
||||
|
||||
&.pf-map-connection-wh-size-xl{
|
||||
|
||||
&:after{
|
||||
content: 'XL';
|
||||
}
|
||||
}
|
||||
|
||||
&.pf-map-connection-preserve-mass{
|
||||
|
||||
&:after{
|
||||
content: 'save mass';
|
||||
background-color: $red-darker;
|
||||
color: $gray-lightest;
|
||||
padding: 0px 3px;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: -6px;
|
||||
font-family: $font-family-bold;
|
||||
@include border-radius(3px);
|
||||
left: calc(50% - 28px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1313,8 +1368,8 @@ table{
|
||||
}
|
||||
|
||||
&.pf-wh-frig{
|
||||
border-top-style: dashed;
|
||||
border-bottom-style: dashed;
|
||||
border-top-style: dotted;
|
||||
border-bottom-style: dotted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,6 +283,20 @@ $mapBubbleWidth: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
// class gets applied to body tag if system/connection gets dragged
|
||||
// to prevent cursor "flicker" we need to change the cursor for "neighbored" elements
|
||||
.jtk-drag-select{
|
||||
.pf-map{
|
||||
cursor: grab !important;
|
||||
.pf-system{
|
||||
cursor: grab !important;
|
||||
.pf-system-head{
|
||||
cursor: grab !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pf-map{
|
||||
width: $mapWidth;
|
||||
height: $mapHeight;
|
||||
@@ -607,6 +621,7 @@ $mapBubbleWidth: 30px;
|
||||
.jtk-connector{
|
||||
z-index: 40; // min z-index for connections
|
||||
cursor: pointer;
|
||||
overflow: unset; // fixes a strange 1px flicker issue when connection is hovered and "jumps" up+down
|
||||
@include transition(stroke 0.18s ease-out, opacity 0.18s ease-out);
|
||||
will-change: all;
|
||||
|
||||
@@ -713,10 +728,11 @@ $mapBubbleWidth: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.pf-map-connection-frig{
|
||||
.pf-map-connection-wh-size-s,
|
||||
.pf-map-connection-wh-size-m {
|
||||
|
||||
path:nth-child(2){
|
||||
stroke-linecap: square !important;
|
||||
stroke-linecap: square !important; // smoother look for "inner" path
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,7 +761,7 @@ $mapBubbleWidth: 30px;
|
||||
}
|
||||
|
||||
%map-overlay{
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
z-index: 1020;
|
||||
background-color: $gray;
|
||||
color: $gray-lighter;
|
||||
@@ -756,15 +772,15 @@ $mapBubbleWidth: 30px;
|
||||
line-height: 14px;
|
||||
padding: 1px 4px;
|
||||
@include border-radius(6px);
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0,.4));
|
||||
@include box-shadow(0 3px 6px rgba(0,0,0,.3));
|
||||
|
||||
&.small{
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: Arial, sans-serif; // fix for element width on custom font family
|
||||
padding: 2px;
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 1px 2px;
|
||||
line-height: 12px;
|
||||
min-width: 14px;
|
||||
@include border-radius(3px);
|
||||
@include box-shadow(0 3px 6px rgba(0,0,0,.3));
|
||||
}
|
||||
|
||||
&.icon{
|
||||
@@ -776,7 +792,6 @@ $mapBubbleWidth: 30px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
@include border-radius(50%);
|
||||
@include box-shadow(0 3px 6px rgba(0,0,0,.3));
|
||||
}
|
||||
|
||||
&.debug{
|
||||
@@ -853,6 +868,10 @@ $mapBubbleWidth: 30px;
|
||||
i{
|
||||
width: 20px;
|
||||
pointer-events: none;
|
||||
|
||||
&.fa-char:before{
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
|
||||
// nested (sub) menu
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
text-transform: capitalize;
|
||||
font-family: $font-family-readable;
|
||||
font-weight: bold;
|
||||
|
||||
kbd{
|
||||
font-size: 80%;
|
||||
line-height: 80%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-content {
|
||||
|
||||
@@ -230,22 +230,21 @@
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
&.pf-map-connection-frig{
|
||||
width: 32px;
|
||||
|
||||
&:after{
|
||||
left: 4px;
|
||||
}
|
||||
&[class*=' pf-map-connection-wh-size-']{
|
||||
width: 25px;
|
||||
}
|
||||
&.pf-map-connection-preserve-mass{
|
||||
width: 26px;
|
||||
|
||||
&:after{
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
&.pf-map-connection-preserve-mass{
|
||||
&:after{
|
||||
content: "\f071";
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
left: 4px;
|
||||
left: calc(50% - 7px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user