- Improved auto added system positioning, reduces overlapping, closed #845
This commit is contained in:
@@ -878,6 +878,7 @@ class Map extends Controller\AccessController {
|
||||
$getMapUserData = (bool)$postData['getMapUserData'];
|
||||
$mapTracking = (bool)$postData['mapTracking'];
|
||||
$systemData = (array)$postData['systemData'];
|
||||
$newSystemPositions = (array)$postData['newSystemPositions'];
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$return = (object)[];
|
||||
@@ -893,7 +894,7 @@ class Map extends Controller\AccessController {
|
||||
if( !is_null($map = $activeCharacter->getMap($mapId)) ){
|
||||
// check character log (current system) and manipulate map (e.g. add new system)
|
||||
if($mapTracking){
|
||||
$map = $this->updateMapByCharacter($map, $activeCharacter);
|
||||
$map = $this->updateMapByCharacter($map, $activeCharacter, $newSystemPositions);
|
||||
}
|
||||
|
||||
// mapUserData ----------------------------------------------------------------------------------------
|
||||
@@ -938,10 +939,11 @@ class Map extends Controller\AccessController {
|
||||
* update map connections/systems based on $character´s location logs
|
||||
* @param Pathfinder\MapModel $map
|
||||
* @param Pathfinder\CharacterModel $character
|
||||
* @param array $newSystemPositions
|
||||
* @return Pathfinder\MapModel
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function updateMapByCharacter(Pathfinder\MapModel $map, Pathfinder\CharacterModel $character) : Pathfinder\MapModel {
|
||||
protected function updateMapByCharacter(Pathfinder\MapModel $map, Pathfinder\CharacterModel $character, array $newSystemPositions = []) : Pathfinder\MapModel {
|
||||
// map changed. update cache (system/connection) changed
|
||||
$mapDataChanged = false;
|
||||
|
||||
@@ -958,6 +960,9 @@ class Map extends Controller\AccessController {
|
||||
$sourceSystemId = (int)$sourceLog->systemId;
|
||||
|
||||
if($sourceSystemId){
|
||||
$defaultPositions = (array)$newSystemPositions['defaults'];
|
||||
$currentPosition = (array)$newSystemPositions['location'];
|
||||
|
||||
$sourceSystem = null;
|
||||
$targetSystem = null;
|
||||
|
||||
@@ -969,8 +974,8 @@ class Map extends Controller\AccessController {
|
||||
// system coordinates for system tha might be added next
|
||||
$systemOffsetX = 130;
|
||||
$systemOffsetY = 0;
|
||||
$systemPosX = 0;
|
||||
$systemPosY = 30;
|
||||
$systemPosX = ((int)$defaultPositions[0]['x']) ? : 0;
|
||||
$systemPosY = ((int)$defaultPositions[0]['y']) ? : 30;
|
||||
|
||||
// check if previous (solo) system is already on the map ----------------------------------------------
|
||||
$sourceSystem = $map->getSystemByCCPId($sourceSystemId, [AbstractModel::getFilter('active', true)]);
|
||||
@@ -978,12 +983,10 @@ class Map extends Controller\AccessController {
|
||||
// if systems don´t already exists on map -> get "blank" system
|
||||
// -> required for system type check (e.g. wormhole, k-space)
|
||||
if($sourceSystem){
|
||||
// system exists
|
||||
$sourceExists = true;
|
||||
|
||||
// system exists -> add target to the "right"
|
||||
$systemPosX = $sourceSystem->posX + $systemOffsetX;
|
||||
$systemPosY = $sourceSystem->posY + $systemOffsetY;
|
||||
}else{
|
||||
// system not exists -> get"blank" system
|
||||
$sourceSystem = $map->getNewSystem($sourceSystemId);
|
||||
}
|
||||
|
||||
@@ -998,6 +1001,11 @@ class Map extends Controller\AccessController {
|
||||
|
||||
if($targetSystem){
|
||||
$targetExists = true;
|
||||
|
||||
if($targetSystemId === (int)$currentPosition['systemId']){
|
||||
$systemPosX = (int)$currentPosition['position']['x'];
|
||||
$systemPosY = (int)$currentPosition['position']['y'];
|
||||
}
|
||||
}else{
|
||||
$targetSystem = $map->getNewSystem($targetSystemId);
|
||||
}
|
||||
@@ -1098,9 +1106,15 @@ class Map extends Controller\AccessController {
|
||||
$map = $sourceSystem->mapId;
|
||||
$sourceExists = true;
|
||||
$mapDataChanged = true;
|
||||
// increase system position (prevent overlapping)
|
||||
$systemPosX = $sourceSystem->posX + $systemOffsetX;
|
||||
$systemPosY = $sourceSystem->posY + $systemOffsetY;
|
||||
|
||||
if(!empty($defaultPositions[1])){
|
||||
$systemPosX = (int)$defaultPositions[1]['x'];
|
||||
$systemPosY = (int)$defaultPositions[1]['y'];
|
||||
}else{
|
||||
// increase system position (prevent overlapping)
|
||||
$systemPosX = $sourceSystem->posX + $systemOffsetX;
|
||||
$systemPosY = $sourceSystem->posY + $systemOffsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ use lib\logging;
|
||||
|
||||
class MapModel extends AbstractMapTrackingModel {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'map';
|
||||
|
||||
/**
|
||||
@@ -27,6 +30,9 @@ class MapModel extends AbstractMapTrackingModel {
|
||||
const ERROR_SLACK_CHANNEL = 'Invalid #Slack channel column [%s]';
|
||||
const ERROR_DISCORD_CHANNEL = 'Invalid #Discord channel column [%s]';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
|
||||
@@ -6,41 +6,50 @@ define(() => {
|
||||
constructor(config){
|
||||
this._defaultConfig = {
|
||||
container: null, // parent DOM container element
|
||||
center: null, // DOM elements that works as center
|
||||
center: null, // DOM element OR [x,y] coordinates that works as center
|
||||
elementClass: 'pf-system', // class for all elements
|
||||
defaultSteps: 8, // how many potential dimensions are checked on en ellipsis around the center
|
||||
defaultGapX: 50,
|
||||
defaultGapY: 50,
|
||||
gapX: 50, // leave gap between elements (x-axis)
|
||||
gapY: 50, // leave gap between elements (y-axis)
|
||||
minX: 0, // min x for valid elements
|
||||
minY: 0, // min y for valid elements
|
||||
spacingX: 20, // spacing x between elements
|
||||
spacingY: 10, // spacing y between elements
|
||||
loops: 2, // max loops around "center" for search
|
||||
grid: false, // set to [20, 20] to force grid snapping
|
||||
newElementWidth: 100, // width for new element
|
||||
newElementHeight: 22, // height for new element
|
||||
mirrorSearch: false, // if true coordinates are "mirrored" for an "alternating" search
|
||||
debug: false, // render debug elements
|
||||
debugOk: false, // if true, only not overlapped dimensions are rendered for debug
|
||||
debugElementClass: 'pf-system-debug' // class for debug elements
|
||||
};
|
||||
|
||||
this._config = Object.assign({}, this._defaultConfig, config);
|
||||
|
||||
this._config.dimensionCache = {};
|
||||
|
||||
this._cacheKey = (dim, depth) => ['dim', dim.left, dim.top, dim.width, dim.height, depth].join('_');
|
||||
|
||||
/**
|
||||
* convert degree into radial unit
|
||||
* @param deg
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
this._degToRad = (deg) => {
|
||||
return deg * Math.PI / 180;
|
||||
};
|
||||
this._degToRad = deg => deg * Math.PI / 180;
|
||||
|
||||
/**
|
||||
* get element dimension/position of a DOM element
|
||||
* @param element
|
||||
* @returns {*}
|
||||
* @param spacingX
|
||||
* @param spacingY
|
||||
* @returns {{a: *, b: *, top: *, left: *, width: *, height: *}}
|
||||
* @private
|
||||
*/
|
||||
this._getElementDimension = element => {
|
||||
let dim = null;
|
||||
|
||||
this._getElementDimension = (element, spacingX = 0, spacingY = 0) => {
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let a = 0;
|
||||
@@ -49,7 +58,7 @@ define(() => {
|
||||
let height = this._config.newElementHeight;
|
||||
|
||||
if(Array.isArray(element)){
|
||||
// xy coordinates
|
||||
// x/y coordinates
|
||||
let point = [
|
||||
element[0] ? parseInt(element[0], 10) : 0,
|
||||
element[1] ? parseInt(element[1], 10) : 0
|
||||
@@ -63,14 +72,21 @@ define(() => {
|
||||
top = point[1];
|
||||
a = this._config.gapX;
|
||||
b = this._config.gapY;
|
||||
}else if(element){
|
||||
}else if(element instanceof Element){
|
||||
// DOM element
|
||||
left = element.style.left ? parseInt(element.style.left, 10) : 0;
|
||||
top = element.style.top ? parseInt(element.style.top, 10) : 0;
|
||||
a = parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX;
|
||||
b = parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY;
|
||||
width = element.offsetWidth;
|
||||
height = element.offsetHeight;
|
||||
left = (element.style.left ? parseInt(element.style.left, 10) : 0) - spacingX;
|
||||
top = (element.style.top ? parseInt(element.style.top, 10) : 0) - spacingY;
|
||||
a = parseInt((element.offsetWidth / 2).toString(), 10) + spacingX + this._config.gapX;
|
||||
b = parseInt((element.offsetHeight / 2).toString(), 10) + spacingY + this._config.gapY;
|
||||
width = element.offsetWidth + 2 * spacingX;
|
||||
height = element.offsetHeight + 2 * spacingY;
|
||||
}else if(element instanceof Object){
|
||||
left = element.left - spacingX;
|
||||
top = element.top - spacingY;
|
||||
a = parseInt((element.width / 2).toString(), 10) + spacingX + this._config.gapX;
|
||||
b = parseInt((element.height / 2).toString(), 10) + spacingY + this._config.gapY;
|
||||
width = element.width + 2 * spacingX;
|
||||
height = element.height + 2 * spacingY;
|
||||
}
|
||||
|
||||
// add "gap" to a and b in order to have some space around elements
|
||||
@@ -121,7 +137,7 @@ define(() => {
|
||||
let dimensions = [];
|
||||
let surroundingElements = this._getContainer().getElementsByClassName(this._config.elementClass);
|
||||
for(let element of surroundingElements){
|
||||
dimensions.push(this._getElementDimension(element));
|
||||
dimensions.push(this._getElementDimension(element, this._config.spacingX, this._config.spacingY));
|
||||
}
|
||||
return dimensions;
|
||||
};
|
||||
@@ -132,7 +148,7 @@ define(() => {
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._transformPointToGrid = (point) => {
|
||||
this._transformPointToGrid = point => {
|
||||
point[0] = Math.floor(point[0] / this._config.grid[0]) * this._config.grid[0];
|
||||
point[1] = Math.floor(point[1] / this._config.grid[1]) * this._config.grid[1];
|
||||
return point;
|
||||
@@ -231,31 +247,44 @@ define(() => {
|
||||
return percent;
|
||||
};
|
||||
|
||||
/**
|
||||
* checks whether dim11 has valid x/y coordinate
|
||||
* -> coordinates are >= "minX/Y" limit
|
||||
* @param dim1
|
||||
* @returns {*|boolean}
|
||||
* @private
|
||||
*/
|
||||
this._valid = dim1 => dim1 && dim1.left >= this._config.minX && dim1.top >= this._config.minY;
|
||||
|
||||
/**
|
||||
* checks whether dim1 is partially overlapped by any other element
|
||||
* @param dim1
|
||||
* @param dimensionContainer
|
||||
* @param allDimensions
|
||||
* @param depth
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._isOverlapping = (dim1, dimensionContainer, allDimensions) => {
|
||||
this._isOverlapping = (dim1, dimensionContainer, allDimensions, depth) => {
|
||||
let isOverlapping = false;
|
||||
if(dim1){
|
||||
if(this._percentCovered(dimensionContainer, dim1 ) === 100){
|
||||
let cacheKey = this._cacheKey(dim1, depth);
|
||||
// check cache first (e.g. if grid is active some dimensions would be checked multiple times)
|
||||
if(this._config.dimensionCache[cacheKey]){
|
||||
return true;
|
||||
}else if(this._percentCovered(dimensionContainer, dim1) === 100){
|
||||
// element is within parent container
|
||||
for(let dim2 of allDimensions){
|
||||
let percentCovered = this._percentCovered(dim1, dim2);
|
||||
if(percentCovered){
|
||||
isOverlapping = true;
|
||||
// render debug element
|
||||
this._showDebugElement(dim1, percentCovered);
|
||||
this._config.dimensionCache[cacheKey] = percentCovered;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
this._showDebugElement(dim1, 100);
|
||||
this._config.dimensionCache[cacheKey] = 100;
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
@@ -264,36 +293,63 @@ define(() => {
|
||||
return isOverlapping;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dim1
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._existDimension = function(dim1){
|
||||
return (
|
||||
dim1.left === this.left &&
|
||||
dim1.top === this.top &&
|
||||
dim1.width === this.width &&
|
||||
dim1.height === this.height
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* find all dimensions around a centerDimension that are not overlapped by other elements
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @param allDimensions
|
||||
* @param depth
|
||||
* @param loops
|
||||
* @returns {Array}
|
||||
* @private
|
||||
*/
|
||||
this._findDimensions = (maxResults, steps, allDimensions, loops) => {
|
||||
this._findDimensions = (maxResults, steps, allDimensions, depth, loops) => {
|
||||
steps = steps || 1;
|
||||
loops = loops || 1;
|
||||
|
||||
let dimensions = [];
|
||||
let start = 0;
|
||||
let end = 360;
|
||||
let angle = end / steps;
|
||||
|
||||
// as default coordinates get checked clockwise Q4 -> Q3 -> Q2 -> Q1
|
||||
// we could also check "mirrored" coordinates Q4+Q1 -> Q3+Q2
|
||||
if(this._config.mirrorSearch){
|
||||
end /= end;
|
||||
}
|
||||
|
||||
let dimensionContainer = this._getElementDimension(this._getContainer());
|
||||
steps = steps || 1;
|
||||
loops = loops || 1;
|
||||
|
||||
if(loops === 1){
|
||||
// check center element
|
||||
let centerDimension = this._getElementDimension(this._config.center);
|
||||
if(!this._isOverlapping(centerDimension, dimensionContainer, allDimensions)){
|
||||
if(
|
||||
this._valid(centerDimension) &&
|
||||
!dimensions.some(this._existDimension, centerDimension) &&
|
||||
!this._isOverlapping(centerDimension, dimensionContainer, allDimensions, depth)
|
||||
){
|
||||
dimensions.push({
|
||||
left: centerDimension.left,
|
||||
top: centerDimension.top,
|
||||
width: centerDimension.width,
|
||||
height: centerDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(centerDimension, 0);
|
||||
this._config.dimensionCache[this._cacheKey(centerDimension, depth)] = 0;
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
@@ -308,27 +364,38 @@ define(() => {
|
||||
while(maxResults > 0 && start < end){
|
||||
// get all potential coordinates on an eclipse around a given "centerElementDimension"
|
||||
let coordinate = this._getEllipseCoordinates(centerDimension, end);
|
||||
// transform relative x/y coordinate into a absolute 2D area
|
||||
let checkDimension = this._transformCoordinate(centerDimension, coordinate);
|
||||
if(!this._isOverlapping(checkDimension, dimensionContainer, allDimensions)){
|
||||
dimensions.push({
|
||||
left: checkDimension.left,
|
||||
top: checkDimension.top,
|
||||
width: checkDimension.width,
|
||||
height: checkDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(checkDimension, 0);
|
||||
|
||||
maxResults--;
|
||||
let coordinates = [coordinate];
|
||||
if(this._config.mirrorSearch && coordinate){
|
||||
coordinates.push({x: coordinate.x, y: coordinate.y * -1 });
|
||||
}
|
||||
|
||||
for(let coordinateTemp of coordinates){
|
||||
// transform relative x/y coordinate into a absolute 2D area
|
||||
let checkDimension = this._transformCoordinate(centerDimension, coordinateTemp);
|
||||
if(
|
||||
this._valid(checkDimension) &&
|
||||
!dimensions.some(this._existDimension, checkDimension) &&
|
||||
!this._isOverlapping(checkDimension, dimensionContainer, allDimensions, depth)
|
||||
){
|
||||
dimensions.push({
|
||||
left: checkDimension.left,
|
||||
top: checkDimension.top,
|
||||
width: checkDimension.width,
|
||||
height: checkDimension.height
|
||||
});
|
||||
this._config.dimensionCache[this._cacheKey(checkDimension, depth)] = 0;
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
}
|
||||
|
||||
end -= angle;
|
||||
}
|
||||
|
||||
if(maxResults > 0 && loops < this._config.loops){
|
||||
loops++;
|
||||
steps *= 2;
|
||||
dimensions = dimensions.concat(this._findDimensions(maxResults, steps, allDimensions, loops));
|
||||
dimensions = dimensions.concat(this._findDimensions(maxResults, steps, allDimensions, depth, loops));
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
@@ -346,21 +413,33 @@ define(() => {
|
||||
/**
|
||||
* render debug element into parent container
|
||||
* -> checks overlapping dimension with other elements
|
||||
* @param dimension
|
||||
* @param percentCovered
|
||||
* @private
|
||||
*/
|
||||
this._showDebugElement = (dimension, percentCovered) => {
|
||||
this._showDebugElements = () => {
|
||||
if(this._config.debug){
|
||||
let element = document.createElement('div');
|
||||
element.style.left = dimension.left + 'px';
|
||||
element.style.top = dimension.top + 'px';
|
||||
element.style.width = dimension.width + 'px';
|
||||
element.style.height = dimension.height + 'px';
|
||||
element.style.backgroundColor = Boolean(percentCovered) ? 'rgba(255,0,0,0.1)' : 'rgba(0,255,0,0.1)';
|
||||
element.innerHTML = Math.round(percentCovered * 100) / 100 + '%';
|
||||
element.classList.add(this._config.debugElementClass);
|
||||
this._getContainer().appendChild(element);
|
||||
let documentFragment = document.createDocumentFragment();
|
||||
for(let [cacheKey, percentCovered] of Object.entries(this._config.dimensionCache)){
|
||||
if(this._config.debugOk && percentCovered){
|
||||
continue;
|
||||
}
|
||||
|
||||
let element = document.createElement('div');
|
||||
let dimParts = cacheKey.split('_');
|
||||
element.style.left = dimParts[1] + 'px';
|
||||
element.style.top = dimParts[2] + 'px';
|
||||
element.style.width = dimParts[3] + 'px';
|
||||
element.style.height = dimParts[4] + 'px';
|
||||
element.style.backgroundColor = Boolean(percentCovered) ? 'rgba(255,0,0,0.1)' : 'rgba(0,255,0,0.4)';
|
||||
element.style.opacity = Boolean(percentCovered) ? 0.5 : 1;
|
||||
element.style.zIndex = Boolean(percentCovered) ? 1000 : 2000;
|
||||
element.style.border = Boolean(percentCovered) ? 'none' : '1px solid rgba(0,255,0,0.3)';
|
||||
element.innerHTML = Math.round(percentCovered * 100) / 100 + '';
|
||||
element.classList.add(this._config.debugElementClass);
|
||||
element.setAttribute('data-depth', dimParts[5]);
|
||||
documentFragment.appendChild(element);
|
||||
}
|
||||
|
||||
this._getContainer().appendChild(documentFragment);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -381,15 +460,45 @@ define(() => {
|
||||
/**
|
||||
* search for surrounding, non overlapping dimensions
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
this.findNonOverlappingDimensions = (maxResults, steps) => {
|
||||
this.findNonOverlappingDimensions = (maxResults, findChain = false) => {
|
||||
this._hideDebugElements();
|
||||
this._config.dimensionCache = {};
|
||||
|
||||
// element dimensions that exist and should be checked for overlapping
|
||||
let allDimensions = this._getAllElementDimensions();
|
||||
let dimensions = [];
|
||||
let depth = 1;
|
||||
let maxDepth = findChain ? maxResults : 1;
|
||||
maxResults = findChain ? 1 : maxResults;
|
||||
while(depth <= maxDepth){
|
||||
let dimensionsTemp = this._findDimensions(maxResults, this._config.defaultSteps, allDimensions, depth);
|
||||
|
||||
return this._findDimensions(maxResults, steps, allDimensions);
|
||||
if(dimensionsTemp.length){
|
||||
dimensions = dimensions.concat(dimensionsTemp);
|
||||
|
||||
if(findChain){
|
||||
// if depth > 0 we have 2D dimension as "center" (not a x/y coordinate)
|
||||
// -> increase the gap
|
||||
this._config.defaultGapX = 10;
|
||||
this._config.defaultGapY = 10;
|
||||
this._config.gapX = 50;
|
||||
this._config.gapY = 50;
|
||||
this._config.center = dimensionsTemp[0];
|
||||
allDimensions = allDimensions.concat([this._getElementDimension(dimensionsTemp[0], this._config.spacingX, this._config.spacingY)]);
|
||||
}
|
||||
|
||||
depth++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._showDebugElements();
|
||||
|
||||
return dimensions;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,20 +662,10 @@ define([
|
||||
case 'add_system':
|
||||
// add new system dialog
|
||||
let position = Layout.getEventCoordinates(e);
|
||||
|
||||
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
|
||||
let positionFinder = new Layout.Position({
|
||||
container: mapElement[0],
|
||||
center: [position.x, position.y],
|
||||
loops: 5,
|
||||
defaultGapX: 10,
|
||||
defaultGapY: 10,
|
||||
grid: mapElement.hasClass(MapUtil.config.mapGridClass) ? grid : false,
|
||||
debug: false
|
||||
let dimensions = MapUtil.newSystemPositionByCoordinates(mapElement, {
|
||||
center: [position.x, position.y]
|
||||
});
|
||||
|
||||
let dimensions = positionFinder.findNonOverlappingDimensions(1, 8);
|
||||
|
||||
if(dimensions.length){
|
||||
position.x = dimensions[0].left;
|
||||
position.y = dimensions[0].top;
|
||||
|
||||
@@ -9,9 +9,8 @@ define([
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/layout',
|
||||
'app/map/magnetizing'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout, Magnetizer) => {
|
||||
], ($, Init, Util, bootbox, MapUtil, Magnetizer) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -245,7 +244,7 @@ define([
|
||||
sourceSystem = options.sourceSystem;
|
||||
|
||||
// get new position
|
||||
newPosition = calculateNewSystemPosition(sourceSystem);
|
||||
newPosition = newSystemPositionBySystem(sourceSystem);
|
||||
}else if(options.position){
|
||||
// check mouse cursor position (add system to map)
|
||||
newPosition = {
|
||||
@@ -730,25 +729,16 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relativ to a source system
|
||||
* calculate the x/y coordinates for a new system - relative to a source system
|
||||
* -> in case no coordinates found -> return default calculated coordinates
|
||||
* @param sourceSystem
|
||||
* @returns {{x: *, y: *}}
|
||||
*/
|
||||
let calculateNewSystemPosition = sourceSystem => {
|
||||
let mapContainer = sourceSystem.parent();
|
||||
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
|
||||
let newSystemPositionBySystem = sourceSystem => {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
let positionFinder = new Layout.Position({
|
||||
container: mapContainer[0],
|
||||
center: sourceSystem[0],
|
||||
loops: 4,
|
||||
grid: mapContainer.hasClass(MapUtil.config.mapGridClass) ? grid : false,
|
||||
debug: false
|
||||
});
|
||||
|
||||
let dimensions = positionFinder.findNonOverlappingDimensions(1, 16);
|
||||
let dimensions = MapUtil.newSystemPositionBySystem(sourceSystem);
|
||||
if(dimensions.length){
|
||||
//... empty map space found
|
||||
x = dimensions[0].left;
|
||||
|
||||
@@ -6,9 +6,10 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/layout',
|
||||
'app/map/scrollbar',
|
||||
'app/map/overlay/util'
|
||||
], ($, Init, Util, Scrollbar, MapOverlayUtil) => {
|
||||
], ($, Init, Util, Layout, Scrollbar, MapOverlayUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -2112,6 +2113,132 @@ define([
|
||||
return hasAccess;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* @param maxResults
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
let findNonOverlappingDimensions = (options = {}, maxResults = 1, findChain = false) => {
|
||||
let defaultOptions = {
|
||||
center: [0, 30],
|
||||
loops: 4,
|
||||
debug: false
|
||||
};
|
||||
|
||||
options = Object.assign({}, defaultOptions, options);
|
||||
let positionFinder = new Layout.Position(Object.assign({}, defaultOptions, options));
|
||||
|
||||
return positionFinder.findNonOverlappingDimensions(maxResults, findChain);
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relative to a source system
|
||||
* @param sourceSystem
|
||||
* @returns {Array}
|
||||
*/
|
||||
let newSystemPositionBySystem = sourceSystem => {
|
||||
let mapContainer = sourceSystem.parent();
|
||||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||||
|
||||
let options = {
|
||||
container: mapContainer[0],
|
||||
center: sourceSystem[0],
|
||||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false
|
||||
};
|
||||
|
||||
return findNonOverlappingDimensions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relative to x/y position
|
||||
* @param mapContainer
|
||||
* @param options
|
||||
* @param maxResults
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
let newSystemPositionByCoordinates = (mapContainer, options = {}, maxResults = 1, findChain = false) => {
|
||||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||||
|
||||
let defaultOptions = {
|
||||
container: mapContainer[0],
|
||||
center: [0, 0],
|
||||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false,
|
||||
loops: 10,
|
||||
defaultGapX: 10,
|
||||
defaultGapY: 10,
|
||||
//debugOk: true,
|
||||
//debug: true
|
||||
};
|
||||
|
||||
options = Object.assign({}, defaultOptions, options);
|
||||
|
||||
return findNonOverlappingDimensions(options, maxResults, findChain);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mapContainer
|
||||
*/
|
||||
let newSystemPositionsByMap = mapContainer => {
|
||||
let positions = {};
|
||||
|
||||
if(mapContainer){
|
||||
let mapId = mapContainer.data('id');
|
||||
let scrollPosition = {
|
||||
x: Math.abs(parseInt(mapContainer.attr('data-scroll-left')) || 0),
|
||||
y: Math.abs(parseInt(mapContainer.attr('data-scroll-top')) || 0)
|
||||
};
|
||||
|
||||
// space new positions from map top (e.g. used for tooltips)
|
||||
scrollPosition.y = Math.max(scrollPosition.y, 30);
|
||||
|
||||
// default position -> current map section top/left -------------------------------------------------------
|
||||
positions.defaults = [scrollPosition];
|
||||
|
||||
// check default position for overlapping -----------------------------------------------------------------
|
||||
let dimensions = newSystemPositionByCoordinates(mapContainer, {
|
||||
center: [scrollPosition.x, scrollPosition.y],
|
||||
minX: scrollPosition.x,
|
||||
minY: scrollPosition.y
|
||||
}, 2, true);
|
||||
|
||||
if(dimensions.length){
|
||||
positions.defaults = dimensions.map(dim => ({
|
||||
x: parseInt(dim.left) || 0,
|
||||
y: parseInt(dim.top) || 0
|
||||
}));
|
||||
}
|
||||
|
||||
// -> calc possible coordinates for new system that should be used based on current user location ---------
|
||||
let currentLocationData = Util.getCurrentLocationData();
|
||||
if(currentLocationData.id){
|
||||
// ... we need to the PF systemId for 'SelectSystem' trigger
|
||||
let systemData = getSystemData(mapId, currentLocationData.id, 'systemId');
|
||||
if(systemData){
|
||||
let currentSystem = $('#' + getSystemId(mapId, systemData.id));
|
||||
if(currentSystem.length){
|
||||
let dimensions = newSystemPositionBySystem(currentSystem);
|
||||
if(dimensions.length){
|
||||
//... empty map space found
|
||||
positions.location = {
|
||||
systemId: currentLocationData.id,
|
||||
position: {
|
||||
x: dimensions[0].left,
|
||||
y: dimensions[0].top
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(positions).length ? positions : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* get a unique map url for deeplinking
|
||||
* @param mapId
|
||||
@@ -2191,6 +2318,9 @@ define([
|
||||
initWormholeInfoTooltip: initWormholeInfoTooltip,
|
||||
getSystemId: getSystemId,
|
||||
checkRight: checkRight,
|
||||
newSystemPositionBySystem: newSystemPositionBySystem,
|
||||
newSystemPositionByCoordinates: newSystemPositionByCoordinates,
|
||||
newSystemPositionsByMap: newSystemPositionsByMap,
|
||||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||||
};
|
||||
});
|
||||
@@ -9,10 +9,11 @@ define([
|
||||
'app/logging',
|
||||
'app/page',
|
||||
'app/map/worker',
|
||||
'app/map/util',
|
||||
'app/module_map',
|
||||
'app/key',
|
||||
'app/ui/form_element'
|
||||
], ($, Init, Util, Logging, Page, MapWorker, ModuleMap) => {
|
||||
], ($, Init, Util, Logging, Page, MapWorker, MapUtil, ModuleMap) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -464,11 +465,13 @@ define([
|
||||
|
||||
// IMPORTANT: Get user data for ONE map that is currently visible
|
||||
// On later releases this can be easy changed to "full update" all maps for a user
|
||||
//
|
||||
let mapIds = [];
|
||||
let newSystemPositions = null;
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
if(activeMap){
|
||||
mapIds = [ activeMap.data('id') ];
|
||||
mapIds = [activeMap.data('id')];
|
||||
newSystemPositions = MapUtil.newSystemPositionsByMap(activeMap);
|
||||
}
|
||||
|
||||
let updatedUserData = {
|
||||
@@ -478,6 +481,10 @@ define([
|
||||
systemData: Util.getCurrentSystemData()
|
||||
};
|
||||
|
||||
if(newSystemPositions){
|
||||
updatedUserData.newSystemPositions = newSystemPositions;
|
||||
}
|
||||
|
||||
Util.timeStart(logKeyServerUserData);
|
||||
|
||||
$.ajax({
|
||||
|
||||
@@ -208,17 +208,17 @@ define([
|
||||
url = 'https://client'; // fake url
|
||||
break;
|
||||
case 'dotlan':
|
||||
systemName = systemName.replace(/ /g, '_');
|
||||
regionName = regionName.replace(/ /g, '_');
|
||||
let systemNameTemp = systemName.replace(/ /g, '_');
|
||||
let regionNameTemp = regionName.replace(/ /g, '_');
|
||||
if(isWormhole){
|
||||
url = domain + '/system/' + systemName;
|
||||
url = domain + '/system/' + systemNameTemp;
|
||||
}else{
|
||||
url = domain + '/map/' + regionName + '/' + systemName;
|
||||
url = domain + '/map/' + regionNameTemp + '/' + systemNameTemp;
|
||||
}
|
||||
break;
|
||||
case 'eveeye':
|
||||
if(!isWormhole){
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName.replace(/ /g, '_'));
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName);
|
||||
url += '&t=eswkc&o=thera,con_svc,node_sov,sub_sec,sector_fac,tag_mk';
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -530,7 +530,7 @@ define([
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="text-right ' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id) + '"/>' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id, 64) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + Math.max((columnCount - 2), 1) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
@@ -641,7 +641,7 @@ define([
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('type', value, 64) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -675,7 +675,7 @@ define([
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data, 64) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
@@ -869,7 +869,7 @@ define([
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('type', value, 64) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -885,8 +885,11 @@ define([
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = '';
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
// "grouped" regex not supported by FF
|
||||
// let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
// let count = Util.getObjVal(matches, 'groups.count');
|
||||
let matches = /^([a-z0-9\s\-]+) ([MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, '2');
|
||||
|
||||
if(type === 'display'){
|
||||
value = count || 0;
|
||||
@@ -908,17 +911,19 @@ define([
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = cellData;
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, 'groups.system');
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
let moon = Util.getObjVal(matches, 'groups.moon');
|
||||
// "grouped" regex not supported by FF
|
||||
// let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let matches = /^([a-z0-9\s\-]+) ([MDCLXVI]+) (\(\w+\)\s)?\- (moon (\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, '1');
|
||||
let count = Util.getObjVal(matches, '2');
|
||||
let moon = Util.getObjVal(matches, '4');
|
||||
if(systemName === (Util.getObjVal(systemData, 'name') || '')){
|
||||
value = value.slice(systemName.length).trim();
|
||||
if(count){
|
||||
value = value.slice(count.length).trimLeftChars(' \-');
|
||||
}
|
||||
if(moon){
|
||||
let moonCount = Util.getObjVal(matches, 'groups.moonCount');
|
||||
let moonCount = Util.getObjVal(matches, '5');
|
||||
value = value.replace(moon, 'M' + moonCount);
|
||||
}
|
||||
}
|
||||
@@ -960,7 +965,7 @@ define([
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data, 64) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -6,41 +6,50 @@ define(() => {
|
||||
constructor(config){
|
||||
this._defaultConfig = {
|
||||
container: null, // parent DOM container element
|
||||
center: null, // DOM elements that works as center
|
||||
center: null, // DOM element OR [x,y] coordinates that works as center
|
||||
elementClass: 'pf-system', // class for all elements
|
||||
defaultSteps: 8, // how many potential dimensions are checked on en ellipsis around the center
|
||||
defaultGapX: 50,
|
||||
defaultGapY: 50,
|
||||
gapX: 50, // leave gap between elements (x-axis)
|
||||
gapY: 50, // leave gap between elements (y-axis)
|
||||
minX: 0, // min x for valid elements
|
||||
minY: 0, // min y for valid elements
|
||||
spacingX: 20, // spacing x between elements
|
||||
spacingY: 10, // spacing y between elements
|
||||
loops: 2, // max loops around "center" for search
|
||||
grid: false, // set to [20, 20] to force grid snapping
|
||||
newElementWidth: 100, // width for new element
|
||||
newElementHeight: 22, // height for new element
|
||||
mirrorSearch: false, // if true coordinates are "mirrored" for an "alternating" search
|
||||
debug: false, // render debug elements
|
||||
debugOk: false, // if true, only not overlapped dimensions are rendered for debug
|
||||
debugElementClass: 'pf-system-debug' // class for debug elements
|
||||
};
|
||||
|
||||
this._config = Object.assign({}, this._defaultConfig, config);
|
||||
|
||||
this._config.dimensionCache = {};
|
||||
|
||||
this._cacheKey = (dim, depth) => ['dim', dim.left, dim.top, dim.width, dim.height, depth].join('_');
|
||||
|
||||
/**
|
||||
* convert degree into radial unit
|
||||
* @param deg
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
this._degToRad = (deg) => {
|
||||
return deg * Math.PI / 180;
|
||||
};
|
||||
this._degToRad = deg => deg * Math.PI / 180;
|
||||
|
||||
/**
|
||||
* get element dimension/position of a DOM element
|
||||
* @param element
|
||||
* @returns {*}
|
||||
* @param spacingX
|
||||
* @param spacingY
|
||||
* @returns {{a: *, b: *, top: *, left: *, width: *, height: *}}
|
||||
* @private
|
||||
*/
|
||||
this._getElementDimension = element => {
|
||||
let dim = null;
|
||||
|
||||
this._getElementDimension = (element, spacingX = 0, spacingY = 0) => {
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let a = 0;
|
||||
@@ -49,7 +58,7 @@ define(() => {
|
||||
let height = this._config.newElementHeight;
|
||||
|
||||
if(Array.isArray(element)){
|
||||
// xy coordinates
|
||||
// x/y coordinates
|
||||
let point = [
|
||||
element[0] ? parseInt(element[0], 10) : 0,
|
||||
element[1] ? parseInt(element[1], 10) : 0
|
||||
@@ -63,14 +72,21 @@ define(() => {
|
||||
top = point[1];
|
||||
a = this._config.gapX;
|
||||
b = this._config.gapY;
|
||||
}else if(element){
|
||||
}else if(element instanceof Element){
|
||||
// DOM element
|
||||
left = element.style.left ? parseInt(element.style.left, 10) : 0;
|
||||
top = element.style.top ? parseInt(element.style.top, 10) : 0;
|
||||
a = parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX;
|
||||
b = parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY;
|
||||
width = element.offsetWidth;
|
||||
height = element.offsetHeight;
|
||||
left = (element.style.left ? parseInt(element.style.left, 10) : 0) - spacingX;
|
||||
top = (element.style.top ? parseInt(element.style.top, 10) : 0) - spacingY;
|
||||
a = parseInt((element.offsetWidth / 2).toString(), 10) + spacingX + this._config.gapX;
|
||||
b = parseInt((element.offsetHeight / 2).toString(), 10) + spacingY + this._config.gapY;
|
||||
width = element.offsetWidth + 2 * spacingX;
|
||||
height = element.offsetHeight + 2 * spacingY;
|
||||
}else if(element instanceof Object){
|
||||
left = element.left - spacingX;
|
||||
top = element.top - spacingY;
|
||||
a = parseInt((element.width / 2).toString(), 10) + spacingX + this._config.gapX;
|
||||
b = parseInt((element.height / 2).toString(), 10) + spacingY + this._config.gapY;
|
||||
width = element.width + 2 * spacingX;
|
||||
height = element.height + 2 * spacingY;
|
||||
}
|
||||
|
||||
// add "gap" to a and b in order to have some space around elements
|
||||
@@ -121,7 +137,7 @@ define(() => {
|
||||
let dimensions = [];
|
||||
let surroundingElements = this._getContainer().getElementsByClassName(this._config.elementClass);
|
||||
for(let element of surroundingElements){
|
||||
dimensions.push(this._getElementDimension(element));
|
||||
dimensions.push(this._getElementDimension(element, this._config.spacingX, this._config.spacingY));
|
||||
}
|
||||
return dimensions;
|
||||
};
|
||||
@@ -132,7 +148,7 @@ define(() => {
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._transformPointToGrid = (point) => {
|
||||
this._transformPointToGrid = point => {
|
||||
point[0] = Math.floor(point[0] / this._config.grid[0]) * this._config.grid[0];
|
||||
point[1] = Math.floor(point[1] / this._config.grid[1]) * this._config.grid[1];
|
||||
return point;
|
||||
@@ -231,31 +247,44 @@ define(() => {
|
||||
return percent;
|
||||
};
|
||||
|
||||
/**
|
||||
* checks whether dim11 has valid x/y coordinate
|
||||
* -> coordinates are >= "minX/Y" limit
|
||||
* @param dim1
|
||||
* @returns {*|boolean}
|
||||
* @private
|
||||
*/
|
||||
this._valid = dim1 => dim1 && dim1.left >= this._config.minX && dim1.top >= this._config.minY;
|
||||
|
||||
/**
|
||||
* checks whether dim1 is partially overlapped by any other element
|
||||
* @param dim1
|
||||
* @param dimensionContainer
|
||||
* @param allDimensions
|
||||
* @param depth
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._isOverlapping = (dim1, dimensionContainer, allDimensions) => {
|
||||
this._isOverlapping = (dim1, dimensionContainer, allDimensions, depth) => {
|
||||
let isOverlapping = false;
|
||||
if(dim1){
|
||||
if(this._percentCovered(dimensionContainer, dim1 ) === 100){
|
||||
let cacheKey = this._cacheKey(dim1, depth);
|
||||
// check cache first (e.g. if grid is active some dimensions would be checked multiple times)
|
||||
if(this._config.dimensionCache[cacheKey]){
|
||||
return true;
|
||||
}else if(this._percentCovered(dimensionContainer, dim1) === 100){
|
||||
// element is within parent container
|
||||
for(let dim2 of allDimensions){
|
||||
let percentCovered = this._percentCovered(dim1, dim2);
|
||||
if(percentCovered){
|
||||
isOverlapping = true;
|
||||
// render debug element
|
||||
this._showDebugElement(dim1, percentCovered);
|
||||
this._config.dimensionCache[cacheKey] = percentCovered;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
this._showDebugElement(dim1, 100);
|
||||
this._config.dimensionCache[cacheKey] = 100;
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
@@ -264,36 +293,63 @@ define(() => {
|
||||
return isOverlapping;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dim1
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._existDimension = function(dim1){
|
||||
return (
|
||||
dim1.left === this.left &&
|
||||
dim1.top === this.top &&
|
||||
dim1.width === this.width &&
|
||||
dim1.height === this.height
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* find all dimensions around a centerDimension that are not overlapped by other elements
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @param allDimensions
|
||||
* @param depth
|
||||
* @param loops
|
||||
* @returns {Array}
|
||||
* @private
|
||||
*/
|
||||
this._findDimensions = (maxResults, steps, allDimensions, loops) => {
|
||||
this._findDimensions = (maxResults, steps, allDimensions, depth, loops) => {
|
||||
steps = steps || 1;
|
||||
loops = loops || 1;
|
||||
|
||||
let dimensions = [];
|
||||
let start = 0;
|
||||
let end = 360;
|
||||
let angle = end / steps;
|
||||
|
||||
// as default coordinates get checked clockwise Q4 -> Q3 -> Q2 -> Q1
|
||||
// we could also check "mirrored" coordinates Q4+Q1 -> Q3+Q2
|
||||
if(this._config.mirrorSearch){
|
||||
end /= end;
|
||||
}
|
||||
|
||||
let dimensionContainer = this._getElementDimension(this._getContainer());
|
||||
steps = steps || 1;
|
||||
loops = loops || 1;
|
||||
|
||||
if(loops === 1){
|
||||
// check center element
|
||||
let centerDimension = this._getElementDimension(this._config.center);
|
||||
if(!this._isOverlapping(centerDimension, dimensionContainer, allDimensions)){
|
||||
if(
|
||||
this._valid(centerDimension) &&
|
||||
!dimensions.some(this._existDimension, centerDimension) &&
|
||||
!this._isOverlapping(centerDimension, dimensionContainer, allDimensions, depth)
|
||||
){
|
||||
dimensions.push({
|
||||
left: centerDimension.left,
|
||||
top: centerDimension.top,
|
||||
width: centerDimension.width,
|
||||
height: centerDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(centerDimension, 0);
|
||||
this._config.dimensionCache[this._cacheKey(centerDimension, depth)] = 0;
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
@@ -308,27 +364,38 @@ define(() => {
|
||||
while(maxResults > 0 && start < end){
|
||||
// get all potential coordinates on an eclipse around a given "centerElementDimension"
|
||||
let coordinate = this._getEllipseCoordinates(centerDimension, end);
|
||||
// transform relative x/y coordinate into a absolute 2D area
|
||||
let checkDimension = this._transformCoordinate(centerDimension, coordinate);
|
||||
if(!this._isOverlapping(checkDimension, dimensionContainer, allDimensions)){
|
||||
dimensions.push({
|
||||
left: checkDimension.left,
|
||||
top: checkDimension.top,
|
||||
width: checkDimension.width,
|
||||
height: checkDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(checkDimension, 0);
|
||||
|
||||
maxResults--;
|
||||
let coordinates = [coordinate];
|
||||
if(this._config.mirrorSearch && coordinate){
|
||||
coordinates.push({x: coordinate.x, y: coordinate.y * -1 });
|
||||
}
|
||||
|
||||
for(let coordinateTemp of coordinates){
|
||||
// transform relative x/y coordinate into a absolute 2D area
|
||||
let checkDimension = this._transformCoordinate(centerDimension, coordinateTemp);
|
||||
if(
|
||||
this._valid(checkDimension) &&
|
||||
!dimensions.some(this._existDimension, checkDimension) &&
|
||||
!this._isOverlapping(checkDimension, dimensionContainer, allDimensions, depth)
|
||||
){
|
||||
dimensions.push({
|
||||
left: checkDimension.left,
|
||||
top: checkDimension.top,
|
||||
width: checkDimension.width,
|
||||
height: checkDimension.height
|
||||
});
|
||||
this._config.dimensionCache[this._cacheKey(checkDimension, depth)] = 0;
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
}
|
||||
|
||||
end -= angle;
|
||||
}
|
||||
|
||||
if(maxResults > 0 && loops < this._config.loops){
|
||||
loops++;
|
||||
steps *= 2;
|
||||
dimensions = dimensions.concat(this._findDimensions(maxResults, steps, allDimensions, loops));
|
||||
dimensions = dimensions.concat(this._findDimensions(maxResults, steps, allDimensions, depth, loops));
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
@@ -346,21 +413,33 @@ define(() => {
|
||||
/**
|
||||
* render debug element into parent container
|
||||
* -> checks overlapping dimension with other elements
|
||||
* @param dimension
|
||||
* @param percentCovered
|
||||
* @private
|
||||
*/
|
||||
this._showDebugElement = (dimension, percentCovered) => {
|
||||
this._showDebugElements = () => {
|
||||
if(this._config.debug){
|
||||
let element = document.createElement('div');
|
||||
element.style.left = dimension.left + 'px';
|
||||
element.style.top = dimension.top + 'px';
|
||||
element.style.width = dimension.width + 'px';
|
||||
element.style.height = dimension.height + 'px';
|
||||
element.style.backgroundColor = Boolean(percentCovered) ? 'rgba(255,0,0,0.1)' : 'rgba(0,255,0,0.1)';
|
||||
element.innerHTML = Math.round(percentCovered * 100) / 100 + '%';
|
||||
element.classList.add(this._config.debugElementClass);
|
||||
this._getContainer().appendChild(element);
|
||||
let documentFragment = document.createDocumentFragment();
|
||||
for(let [cacheKey, percentCovered] of Object.entries(this._config.dimensionCache)){
|
||||
if(this._config.debugOk && percentCovered){
|
||||
continue;
|
||||
}
|
||||
|
||||
let element = document.createElement('div');
|
||||
let dimParts = cacheKey.split('_');
|
||||
element.style.left = dimParts[1] + 'px';
|
||||
element.style.top = dimParts[2] + 'px';
|
||||
element.style.width = dimParts[3] + 'px';
|
||||
element.style.height = dimParts[4] + 'px';
|
||||
element.style.backgroundColor = Boolean(percentCovered) ? 'rgba(255,0,0,0.1)' : 'rgba(0,255,0,0.4)';
|
||||
element.style.opacity = Boolean(percentCovered) ? 0.5 : 1;
|
||||
element.style.zIndex = Boolean(percentCovered) ? 1000 : 2000;
|
||||
element.style.border = Boolean(percentCovered) ? 'none' : '1px solid rgba(0,255,0,0.3)';
|
||||
element.innerHTML = Math.round(percentCovered * 100) / 100 + '';
|
||||
element.classList.add(this._config.debugElementClass);
|
||||
element.setAttribute('data-depth', dimParts[5]);
|
||||
documentFragment.appendChild(element);
|
||||
}
|
||||
|
||||
this._getContainer().appendChild(documentFragment);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -381,15 +460,45 @@ define(() => {
|
||||
/**
|
||||
* search for surrounding, non overlapping dimensions
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
this.findNonOverlappingDimensions = (maxResults, steps) => {
|
||||
this.findNonOverlappingDimensions = (maxResults, findChain = false) => {
|
||||
this._hideDebugElements();
|
||||
this._config.dimensionCache = {};
|
||||
|
||||
// element dimensions that exist and should be checked for overlapping
|
||||
let allDimensions = this._getAllElementDimensions();
|
||||
let dimensions = [];
|
||||
let depth = 1;
|
||||
let maxDepth = findChain ? maxResults : 1;
|
||||
maxResults = findChain ? 1 : maxResults;
|
||||
while(depth <= maxDepth){
|
||||
let dimensionsTemp = this._findDimensions(maxResults, this._config.defaultSteps, allDimensions, depth);
|
||||
|
||||
return this._findDimensions(maxResults, steps, allDimensions);
|
||||
if(dimensionsTemp.length){
|
||||
dimensions = dimensions.concat(dimensionsTemp);
|
||||
|
||||
if(findChain){
|
||||
// if depth > 0 we have 2D dimension as "center" (not a x/y coordinate)
|
||||
// -> increase the gap
|
||||
this._config.defaultGapX = 10;
|
||||
this._config.defaultGapY = 10;
|
||||
this._config.gapX = 50;
|
||||
this._config.gapY = 50;
|
||||
this._config.center = dimensionsTemp[0];
|
||||
allDimensions = allDimensions.concat([this._getElementDimension(dimensionsTemp[0], this._config.spacingX, this._config.spacingY)]);
|
||||
}
|
||||
|
||||
depth++;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._showDebugElements();
|
||||
|
||||
return dimensions;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,20 +662,10 @@ define([
|
||||
case 'add_system':
|
||||
// add new system dialog
|
||||
let position = Layout.getEventCoordinates(e);
|
||||
|
||||
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
|
||||
let positionFinder = new Layout.Position({
|
||||
container: mapElement[0],
|
||||
center: [position.x, position.y],
|
||||
loops: 5,
|
||||
defaultGapX: 10,
|
||||
defaultGapY: 10,
|
||||
grid: mapElement.hasClass(MapUtil.config.mapGridClass) ? grid : false,
|
||||
debug: false
|
||||
let dimensions = MapUtil.newSystemPositionByCoordinates(mapElement, {
|
||||
center: [position.x, position.y]
|
||||
});
|
||||
|
||||
let dimensions = positionFinder.findNonOverlappingDimensions(1, 8);
|
||||
|
||||
if(dimensions.length){
|
||||
position.x = dimensions[0].left;
|
||||
position.y = dimensions[0].top;
|
||||
|
||||
@@ -9,9 +9,8 @@ define([
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/layout',
|
||||
'app/map/magnetizing'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout, Magnetizer) => {
|
||||
], ($, Init, Util, bootbox, MapUtil, Magnetizer) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -245,7 +244,7 @@ define([
|
||||
sourceSystem = options.sourceSystem;
|
||||
|
||||
// get new position
|
||||
newPosition = calculateNewSystemPosition(sourceSystem);
|
||||
newPosition = newSystemPositionBySystem(sourceSystem);
|
||||
}else if(options.position){
|
||||
// check mouse cursor position (add system to map)
|
||||
newPosition = {
|
||||
@@ -730,25 +729,16 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relativ to a source system
|
||||
* calculate the x/y coordinates for a new system - relative to a source system
|
||||
* -> in case no coordinates found -> return default calculated coordinates
|
||||
* @param sourceSystem
|
||||
* @returns {{x: *, y: *}}
|
||||
*/
|
||||
let calculateNewSystemPosition = sourceSystem => {
|
||||
let mapContainer = sourceSystem.parent();
|
||||
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
|
||||
let newSystemPositionBySystem = sourceSystem => {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
let positionFinder = new Layout.Position({
|
||||
container: mapContainer[0],
|
||||
center: sourceSystem[0],
|
||||
loops: 4,
|
||||
grid: mapContainer.hasClass(MapUtil.config.mapGridClass) ? grid : false,
|
||||
debug: false
|
||||
});
|
||||
|
||||
let dimensions = positionFinder.findNonOverlappingDimensions(1, 16);
|
||||
let dimensions = MapUtil.newSystemPositionBySystem(sourceSystem);
|
||||
if(dimensions.length){
|
||||
//... empty map space found
|
||||
x = dimensions[0].left;
|
||||
|
||||
@@ -6,9 +6,10 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/layout',
|
||||
'app/map/scrollbar',
|
||||
'app/map/overlay/util'
|
||||
], ($, Init, Util, Scrollbar, MapOverlayUtil) => {
|
||||
], ($, Init, Util, Layout, Scrollbar, MapOverlayUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
@@ -2112,6 +2113,132 @@ define([
|
||||
return hasAccess;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* @param maxResults
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
let findNonOverlappingDimensions = (options = {}, maxResults = 1, findChain = false) => {
|
||||
let defaultOptions = {
|
||||
center: [0, 30],
|
||||
loops: 4,
|
||||
debug: false
|
||||
};
|
||||
|
||||
options = Object.assign({}, defaultOptions, options);
|
||||
let positionFinder = new Layout.Position(Object.assign({}, defaultOptions, options));
|
||||
|
||||
return positionFinder.findNonOverlappingDimensions(maxResults, findChain);
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relative to a source system
|
||||
* @param sourceSystem
|
||||
* @returns {Array}
|
||||
*/
|
||||
let newSystemPositionBySystem = sourceSystem => {
|
||||
let mapContainer = sourceSystem.parent();
|
||||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||||
|
||||
let options = {
|
||||
container: mapContainer[0],
|
||||
center: sourceSystem[0],
|
||||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false
|
||||
};
|
||||
|
||||
return findNonOverlappingDimensions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relative to x/y position
|
||||
* @param mapContainer
|
||||
* @param options
|
||||
* @param maxResults
|
||||
* @param findChain
|
||||
* @returns {Array}
|
||||
*/
|
||||
let newSystemPositionByCoordinates = (mapContainer, options = {}, maxResults = 1, findChain = false) => {
|
||||
let grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
||||
|
||||
let defaultOptions = {
|
||||
container: mapContainer[0],
|
||||
center: [0, 0],
|
||||
grid: mapContainer.hasClass(config.mapGridClass) ? grid : false,
|
||||
loops: 10,
|
||||
defaultGapX: 10,
|
||||
defaultGapY: 10,
|
||||
//debugOk: true,
|
||||
//debug: true
|
||||
};
|
||||
|
||||
options = Object.assign({}, defaultOptions, options);
|
||||
|
||||
return findNonOverlappingDimensions(options, maxResults, findChain);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mapContainer
|
||||
*/
|
||||
let newSystemPositionsByMap = mapContainer => {
|
||||
let positions = {};
|
||||
|
||||
if(mapContainer){
|
||||
let mapId = mapContainer.data('id');
|
||||
let scrollPosition = {
|
||||
x: Math.abs(parseInt(mapContainer.attr('data-scroll-left')) || 0),
|
||||
y: Math.abs(parseInt(mapContainer.attr('data-scroll-top')) || 0)
|
||||
};
|
||||
|
||||
// space new positions from map top (e.g. used for tooltips)
|
||||
scrollPosition.y = Math.max(scrollPosition.y, 30);
|
||||
|
||||
// default position -> current map section top/left -------------------------------------------------------
|
||||
positions.defaults = [scrollPosition];
|
||||
|
||||
// check default position for overlapping -----------------------------------------------------------------
|
||||
let dimensions = newSystemPositionByCoordinates(mapContainer, {
|
||||
center: [scrollPosition.x, scrollPosition.y],
|
||||
minX: scrollPosition.x,
|
||||
minY: scrollPosition.y
|
||||
}, 2, true);
|
||||
|
||||
if(dimensions.length){
|
||||
positions.defaults = dimensions.map(dim => ({
|
||||
x: parseInt(dim.left) || 0,
|
||||
y: parseInt(dim.top) || 0
|
||||
}));
|
||||
}
|
||||
|
||||
// -> calc possible coordinates for new system that should be used based on current user location ---------
|
||||
let currentLocationData = Util.getCurrentLocationData();
|
||||
if(currentLocationData.id){
|
||||
// ... we need to the PF systemId for 'SelectSystem' trigger
|
||||
let systemData = getSystemData(mapId, currentLocationData.id, 'systemId');
|
||||
if(systemData){
|
||||
let currentSystem = $('#' + getSystemId(mapId, systemData.id));
|
||||
if(currentSystem.length){
|
||||
let dimensions = newSystemPositionBySystem(currentSystem);
|
||||
if(dimensions.length){
|
||||
//... empty map space found
|
||||
positions.location = {
|
||||
systemId: currentLocationData.id,
|
||||
position: {
|
||||
x: dimensions[0].left,
|
||||
y: dimensions[0].top
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(positions).length ? positions : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* get a unique map url for deeplinking
|
||||
* @param mapId
|
||||
@@ -2191,6 +2318,9 @@ define([
|
||||
initWormholeInfoTooltip: initWormholeInfoTooltip,
|
||||
getSystemId: getSystemId,
|
||||
checkRight: checkRight,
|
||||
newSystemPositionBySystem: newSystemPositionBySystem,
|
||||
newSystemPositionByCoordinates: newSystemPositionByCoordinates,
|
||||
newSystemPositionsByMap: newSystemPositionsByMap,
|
||||
getMapDeeplinkUrl: getMapDeeplinkUrl
|
||||
};
|
||||
});
|
||||
@@ -9,10 +9,11 @@ define([
|
||||
'app/logging',
|
||||
'app/page',
|
||||
'app/map/worker',
|
||||
'app/map/util',
|
||||
'app/module_map',
|
||||
'app/key',
|
||||
'app/ui/form_element'
|
||||
], ($, Init, Util, Logging, Page, MapWorker, ModuleMap) => {
|
||||
], ($, Init, Util, Logging, Page, MapWorker, MapUtil, ModuleMap) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -464,11 +465,13 @@ define([
|
||||
|
||||
// IMPORTANT: Get user data for ONE map that is currently visible
|
||||
// On later releases this can be easy changed to "full update" all maps for a user
|
||||
//
|
||||
let mapIds = [];
|
||||
let newSystemPositions = null;
|
||||
let activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
if(activeMap){
|
||||
mapIds = [ activeMap.data('id') ];
|
||||
mapIds = [activeMap.data('id')];
|
||||
newSystemPositions = MapUtil.newSystemPositionsByMap(activeMap);
|
||||
}
|
||||
|
||||
let updatedUserData = {
|
||||
@@ -478,6 +481,10 @@ define([
|
||||
systemData: Util.getCurrentSystemData()
|
||||
};
|
||||
|
||||
if(newSystemPositions){
|
||||
updatedUserData.newSystemPositions = newSystemPositions;
|
||||
}
|
||||
|
||||
Util.timeStart(logKeyServerUserData);
|
||||
|
||||
$.ajax({
|
||||
|
||||
@@ -208,17 +208,17 @@ define([
|
||||
url = 'https://client'; // fake url
|
||||
break;
|
||||
case 'dotlan':
|
||||
systemName = systemName.replace(/ /g, '_');
|
||||
regionName = regionName.replace(/ /g, '_');
|
||||
let systemNameTemp = systemName.replace(/ /g, '_');
|
||||
let regionNameTemp = regionName.replace(/ /g, '_');
|
||||
if(isWormhole){
|
||||
url = domain + '/system/' + systemName;
|
||||
url = domain + '/system/' + systemNameTemp;
|
||||
}else{
|
||||
url = domain + '/map/' + regionName + '/' + systemName;
|
||||
url = domain + '/map/' + regionNameTemp + '/' + systemNameTemp;
|
||||
}
|
||||
break;
|
||||
case 'eveeye':
|
||||
if(!isWormhole){
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName.replace(/ /g, '_'));
|
||||
url = domain + '/?m=' + encodeURIComponent(regionName) + '&s=' + encodeURIComponent(systemName);
|
||||
url += '&t=eswkc&o=thera,con_svc,node_sov,sub_sec,sector_fac,tag_mk';
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -530,7 +530,7 @@ define([
|
||||
'<tr class="group">' +
|
||||
'<td></td>' +
|
||||
'<td class="text-right ' + config.tableCellImageClass + '">' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id) + '"/>' +
|
||||
'<img src="' + Util.eveImageUrl(imgType, group.id, 64) + '"/>' +
|
||||
'</td>' +
|
||||
'<td colspan="' + Math.max((columnCount - 2), 1) + '">' + group.name + '</td>' +
|
||||
'</tr>'
|
||||
@@ -641,7 +641,7 @@ define([
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('type', value, 64) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -675,7 +675,7 @@ define([
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data, 64) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
@@ -869,7 +869,7 @@ define([
|
||||
_: function(data, type, row, meta){
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<img src="' + Util.eveImageUrl('type', value) +'"/>';
|
||||
value = '<img src="' + Util.eveImageUrl('type', value, 64) +'"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -885,8 +885,11 @@ define([
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = '';
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
// "grouped" regex not supported by FF
|
||||
// let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) .*$/i.exec(cellData);
|
||||
// let count = Util.getObjVal(matches, 'groups.count');
|
||||
let matches = /^([a-z0-9\s\-]+) ([MDCLXVI]+) .*$/i.exec(cellData);
|
||||
let count = Util.getObjVal(matches, '2');
|
||||
|
||||
if(type === 'display'){
|
||||
value = count || 0;
|
||||
@@ -908,17 +911,19 @@ define([
|
||||
_: function(cellData, type, rowData, meta){
|
||||
let value = cellData;
|
||||
if(cellData){
|
||||
let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, 'groups.system');
|
||||
let count = Util.getObjVal(matches, 'groups.count');
|
||||
let moon = Util.getObjVal(matches, 'groups.moon');
|
||||
// "grouped" regex not supported by FF
|
||||
// let matches = /^(?<system>[a-z0-9\s\-]+) (?<count>[MDCLXVI]+) (?<label>\(\w+\)\s)?\- (?<moon>moon (?<moonCount>\d)+)?.*$/i.exec(cellData);
|
||||
let matches = /^([a-z0-9\s\-]+) ([MDCLXVI]+) (\(\w+\)\s)?\- (moon (\d)+)?.*$/i.exec(cellData);
|
||||
let systemName = Util.getObjVal(matches, '1');
|
||||
let count = Util.getObjVal(matches, '2');
|
||||
let moon = Util.getObjVal(matches, '4');
|
||||
if(systemName === (Util.getObjVal(systemData, 'name') || '')){
|
||||
value = value.slice(systemName.length).trim();
|
||||
if(count){
|
||||
value = value.slice(count.length).trimLeftChars(' \-');
|
||||
}
|
||||
if(moon){
|
||||
let moonCount = Util.getObjVal(matches, 'groups.moonCount');
|
||||
let moonCount = Util.getObjVal(matches, '5');
|
||||
value = value.replace(moon, 'M' + moonCount);
|
||||
}
|
||||
}
|
||||
@@ -960,7 +965,7 @@ define([
|
||||
let value = data;
|
||||
if(type === 'display' && value){
|
||||
value = '<a href="https://zkillboard.com/corporation/' + data + '/" target="_blank" rel="noopener">';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data) + '"/>';
|
||||
value += '<img src="' + Util.eveImageUrl('corporation', data, 64) + '"/>';
|
||||
value += '</a>';
|
||||
}
|
||||
return value;
|
||||
|
||||
@@ -534,7 +534,18 @@ $mapBubbleWidth: 30px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
font-family: Oxygen, Arial, sans-serif;
|
||||
z-index: 500;
|
||||
|
||||
&:before{
|
||||
content: attr(data-depth);
|
||||
font-family: Oxygen, Arial, sans-serif;
|
||||
position: absolute;
|
||||
line-height: 10px;
|
||||
top: 1px;
|
||||
left: 2px;
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
|
||||
// Endpoints ========================================================================================================
|
||||
|
||||
@@ -160,5 +160,6 @@
|
||||
|
||||
.well{
|
||||
margin-bottom: 0; // overwrite default
|
||||
line-height: 13px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user