* #84 test data dump from CREST login * updated "credits" dialog (Google+ link) fixed login form layout * updated Cortex Data-Mapper * - #84 CREST Login (WIP) - New CREST controller - Database restructuring - improved type-casting for some controller functions - New login process - Fixed some bugs during the setup process (/setup root) - Added CREST request caching by response headers * pathfinder-84 [Feature Request] CREST Pilot Tracking, many smaller Bugfixes * pathfinder-84 [Feature Request] added develop JS files * closed #121 fixed wormhole signature type caching * closed #120 removed map-loading animation for larger maps (same behaviour as IGB) * closed #119 fixed wormhole signature id count * closed #114 Added check for already existing system when adding a new one. (fixed PDO 'duplicate entry' error) * closed #112 fixed DataTables error for missing "status" data (signature table) * closed #111 fixed convertDataToUTC(); client side date transformation * closed #109 fixed system TrueSec rounding * closed #103 fixed system updated timestamp in getData() * fixed CSS class for secStatus in Routes module * closed #121 fixed wormhole signature type caching * changed dateTime format from German to US format fixed some minor bugs in signatureTable module * closed #81 fixed "signature type" overwriting by "signature reader" update * closed #106 added new signature_types form C5/6 wormholes (gas/ore) * closed #129 fixed parameter hinting * closed #131 new "route search" algorithm, added current map systems to live search, added refresh/update functionality for each found route, added bulk route refresh function, added "meta map" route search (search on multiple maps), added route "filters" (restrict search on "stargates", "wormholes", "jumpbridges"), added route "filter" for wormholes (reduced/critical wormholes) closed #89 fixed "loop connections" on same system #84 added error messages for "invalid" CREST "Client ID" added "bootboxjs" (customized styled checkboxes/radio buttons) CSS only "Font Awesome" version upgrade 4.4.0 -> 4.61 "Bootbox.js" version upgrade 4.3.0 -> 4.4.0 fixed "system dialog" (added responsive layout) * closed #134 fixed db column type DT_INT (8 bytes) to DT_BIGINT * closed #138 added new cookie based login * closed #137 fixed javascript errors on trying to establish an "invalid" connection * - #84, #138 improved "character selection" on login page (expired cookies are deleted, character panel layout improvements) - added new "Server info panel" to the login page - added new cronjob to delete expired cookie authentication data * #138 enables character switching between characters which have same user * - PHP Framework upgrade 3.5.0 -> 3.5.1 (fixes some issues with CREST cURL caching, and SESSION management) - #138 added "cookie logout" to "logout" menu entry * - updated "feature page" with new feature descriptions and label - added some new images to the "feature gallery" - removed "beta" status from "magnetizing" feature on map menu - hide "server status" panel on "mobile" breakpoint * - #138 clear character authentication data on sold characters * closed #142 added custom "onsuspect()" session handler * #142 do not log suspect if no file is defined in pathfinder.ini * #142 added NullSec Data/Relic sites to C1/2/3 wormholes as signature option * #144 fixed "Character not found" warning * #144 fixed "Character not found" warning * closed #144 fixed broken routes panel in IGB * updated README.md for upcoming release * #147 response header validation * #149 changed comment for 'BASE' framework var * fixed map import * - added minimal SDE dump (EVE Online: Citadel) - #147 improved CREST API error logging (WIP) - improved SSO controller (removed access_token from public endpoints) * closed #154 added alliance maps to CREST API * - updated Gulp build dependencies - increased CREST timeout from 3s -> 4s - added "Accept" Headers for some CREST endpoints * cloased #147 * - closed #153 added character verification check for getAll(); Signatures Ajax endpoint * - updated README.md (added Slack developer chat information) * Bugfix frig holes (#159) * added missing frigate wormholes and fixed Q003 destination in shattered wormholes * changed C7 to 0.0 for Q003 * - fixed broken "graph" data for system * added a "failover" system for bad crest requests (HTTP status 5xx,.. ) * Red Gaint => Red Giant (#161) * closed #163 added CREST endpoint support for "waypoints" * fixed typo * closed #160 fixed tooltip container * - added new features to login page * closes #154 added alliance map support * fixed XML path for cronjobs * fixed a bug with inactive "private" maps * closes #175 added alternative environment configuration * - v1.0.0 build
3683 lines
131 KiB
JavaScript
3683 lines
131 KiB
JavaScript
/**
|
|
* Main map functionality
|
|
*/
|
|
|
|
define([
|
|
'jquery',
|
|
'app/init',
|
|
'app/util',
|
|
'app/render',
|
|
'bootbox',
|
|
'app/ccp',
|
|
'app/map/magnetizing',
|
|
'dragToSelect',
|
|
'select2',
|
|
'app/map/contextmenu',
|
|
'app/map/overlay'
|
|
], function($, Init, Util, Render, bootbox, CCP, MagnetizerWrapper) {
|
|
|
|
'use strict';
|
|
|
|
var config = {
|
|
zIndexCounter: 110,
|
|
newSystemOffset: {
|
|
x: 130,
|
|
y: 0
|
|
},
|
|
|
|
mapSnapToGridDimension: 20, // px for grid snapping (grid YxY)
|
|
mapSnapToGrid: false, // "Snap to Grid" feature for drag&drop systems on map (optional)
|
|
mapMagnetizer: false, // "Magnetizer" feature for drag&drop systems on map (optional)
|
|
mapTabContentClass: 'pf-map-tab-content', // Tab-Content element (parent element)
|
|
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
|
|
headMapTrackingId: 'pf-head-map-tracking', // id for "map tracking" toggle (checkbox)
|
|
|
|
mapClass: 'pf-map', // class for all maps
|
|
mapGridClass: 'pf-grid-small', // class for map grid snapping
|
|
mapIdPrefix: 'pf-map-', // id prefix for all maps
|
|
systemIdPrefix: 'pf-system-', // id prefix for a system
|
|
systemClass: 'pf-system', // class for all systems
|
|
systemActiveClass: 'pf-system-active', // class for an active system in a map
|
|
systemSelectedClass: 'pf-system-selected', // class for selected systems in a map
|
|
systemLockedClass: 'pf-system-locked', // class for locked systems in a map
|
|
systemHeadClass: 'pf-system-head', // class for system head
|
|
systemHeadNameClass: 'pf-system-head-name', // class for system name
|
|
systemHeadExpandClass: 'pf-system-head-expand', // class for system head expand arrow
|
|
systemBodyClass: 'pf-system-body', // class for system body
|
|
systemBodyItemHeight: 16, // px of a system body entry
|
|
systemBodyItemClass: 'pf-system-body-item', // class for a system body entry
|
|
systemBodyItemStatusClass: 'pf-user-status', // class for player status in system body
|
|
systemBodyItemNameClass: 'pf-system-body-item-name', // class for player name in system body
|
|
systemBodyRightClass: 'pf-system-body-right', // class for player ship name in system body
|
|
systemTooltipInnerClass: 'pf-system-tooltip-inner', // class for system tooltip content
|
|
systemTooltipInnerIdPrefix: 'pf-system-tooltip-inner-', // id prefix for system tooltip content
|
|
dynamicElementWrapperId: 'pf-dialog-wrapper', // wrapper div for dynamic content (dialogs, context-menus,...)
|
|
|
|
// endpoint classes
|
|
endpointSourceClass: 'pf-map-endpoint-source',
|
|
endpointTargetClass: 'pf-map-endpoint-target',
|
|
|
|
// context menus
|
|
mapContextMenuId: 'pf-map-contextmenu',
|
|
connectionContextMenuId: 'pf-map-connection-contextmenu',
|
|
systemContextMenuId: 'pf-map-system-contextmenu',
|
|
|
|
// dialogs
|
|
systemDialogId: 'pf-system-dialog', // id for system dialog
|
|
systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element
|
|
|
|
// system security classes
|
|
systemSec: 'pf-system-sec',
|
|
systemSecHigh: 'pf-system-sec-highSec',
|
|
systemSecLow: 'pf-system-sec-lowSec',
|
|
systemSecNull: 'pf-system-sec-nullSec',
|
|
systemSecWHHeigh: 'pf-system-sec-high',
|
|
systemSecWHMid: 'pf-system-sec-mid',
|
|
systemSecWHLow: 'pf-system-sec-low'
|
|
};
|
|
|
|
// active jsPlumb instances currently running
|
|
var activeInstances = {};
|
|
|
|
// active connections per map (cache object)
|
|
var connectionCache = {};
|
|
|
|
// characterID => systemIds are cached temporary where the active user character is in
|
|
// if a character switches/add system, establish connection with "previous" system
|
|
var activeSystemCache = '';
|
|
|
|
// jsPlumb config
|
|
var globalMapConfig = {
|
|
source: {
|
|
filter: '.' + config.systemHeadNameClass,
|
|
//isSource:true,
|
|
isTarget:true, // add target Endpoint to each system (e.g. for drag&drop)
|
|
allowLoopback: false, // loopBack connections are not allowed
|
|
cssClass: config.endpointSourceClass,
|
|
uniqueEndpoint: false, // each connection has its own endpoint visible
|
|
dragOptions:{
|
|
},
|
|
connectionsDetachable: true, // dragOptions are set -> allow detaching them
|
|
maxConnections: 10, // due to isTarget is true, this is the max count of !out!-going connections
|
|
// isSource:true,
|
|
anchor: 'Continuous'
|
|
},
|
|
target: {
|
|
filter: '.' + config.systemHeadNameClass,
|
|
isSource:true,
|
|
//isTarget:true,
|
|
//allowLoopback: false, // loopback connections are not allowed
|
|
cssClass: config.endpointTargetClass,
|
|
dropOptions: {
|
|
hoverClass: config.systemActiveClass,
|
|
activeClass: 'dragActive'
|
|
},
|
|
// isTarget:true,
|
|
// uniqueEndpoint: false,
|
|
anchor: 'Continuous'
|
|
},
|
|
connectionTypes: Init.connectionTypes
|
|
};
|
|
|
|
/**
|
|
* updates a system with current information
|
|
* @param map
|
|
* @param data
|
|
* @param currentUserIsHere boolean - if the current user is in this system
|
|
*/
|
|
$.fn.updateSystemUserData = function(map, data, currentUserIsHere){
|
|
|
|
var system = $(this);
|
|
var systemId = system.attr('id');
|
|
|
|
// find system body
|
|
var systemBody = $( system.find('.' + config.systemBodyClass) );
|
|
|
|
// find expand arrow
|
|
var systemHeadExpand = $( system.find('.' + config.systemHeadExpandClass) );
|
|
|
|
var oldCacheKey = system.data('userCache');
|
|
var oldUserCount = system.data('userCount');
|
|
oldUserCount = (oldUserCount !== undefined ? oldUserCount : 0);
|
|
var userCounter = 0;
|
|
|
|
system.data('currentUser', false);
|
|
|
|
// if current user is in THIS system trigger event
|
|
if(currentUserIsHere){
|
|
system.data('currentUser', true);
|
|
}
|
|
|
|
// add user information
|
|
if(
|
|
data &&
|
|
data.user
|
|
){
|
|
var cacheArray = [];
|
|
// loop all active pilots and build cache-key
|
|
for(var i = 0; i < data.user.length; i++){
|
|
userCounter++;
|
|
var tempUserData = data.user[i];
|
|
cacheArray.push(tempUserData.id + '_' + tempUserData.log.ship.id);
|
|
}
|
|
var cacheKey = cacheArray.join('_');
|
|
|
|
// check for if cacheKey has changed
|
|
if(cacheKey !== oldCacheKey){
|
|
// set new CacheKey
|
|
system.data('userCache', cacheKey);
|
|
system.data('userCount', userCounter);
|
|
|
|
// remove all content
|
|
systemBody.empty();
|
|
|
|
// loop "again" and build DOM object with user information
|
|
for(var j = 0; j < data.user.length; j++){
|
|
var userData = data.user[j];
|
|
|
|
var statusClass = Util.getStatusInfoForCharacter(userData, 'class');
|
|
var userName = userData.name;
|
|
|
|
var item = $('<div>', {
|
|
class: config.systemBodyItemClass
|
|
}).append(
|
|
$('<span>', {
|
|
text: userData.log.ship.typeName,
|
|
class: config.systemBodyRightClass
|
|
})
|
|
).append(
|
|
$('<i>', {
|
|
class: ['fa', 'fa-circle', config.systemBodyItemStatusClass, statusClass].join(' ')
|
|
})
|
|
).append(
|
|
$('<span>', {
|
|
class: config.systemBodyItemNameClass,
|
|
text: userName
|
|
})
|
|
);
|
|
|
|
systemBody.append(item);
|
|
}
|
|
|
|
|
|
// =================================================================
|
|
|
|
// user count changed -> change tooltip content
|
|
var tooltipOptions = {placement: 'top', trigger: 'manual'};
|
|
|
|
// set tooltip color
|
|
var highlight = false;
|
|
var tooltipIconClass = '';
|
|
if(userCounter > oldUserCount){
|
|
highlight = 'good';
|
|
tooltipIconClass = 'fa-caret-up';
|
|
}else if(userCounter < oldUserCount){
|
|
highlight = 'bad';
|
|
tooltipIconClass = 'fa-caret-down';
|
|
}
|
|
|
|
tooltipOptions.id = systemId;
|
|
tooltipOptions.highlight = highlight;
|
|
tooltipOptions.title = "<i class='fa " + tooltipIconClass + "'></i>";
|
|
tooltipOptions.title += ' ' + userCounter;
|
|
|
|
// show system head
|
|
systemHeadExpand.velocity('stop', true).velocity({
|
|
width: '10px'
|
|
},{
|
|
duration: 50,
|
|
display: 'inline-block',
|
|
progress: function(){
|
|
//revalidate element size and repaint
|
|
map.revalidate( systemId );
|
|
},
|
|
complete: function(){
|
|
// show system body
|
|
system.toggleBody(true, map, {complete: function(system){
|
|
// complete callback function
|
|
// show active user tooltip
|
|
system.toggleSystemTooltip('show', tooltipOptions);
|
|
}});
|
|
}
|
|
});
|
|
}
|
|
}else{
|
|
// no user data found for this system
|
|
system.data('userCache', false);
|
|
system.data('userCount', 0);
|
|
systemBody.empty();
|
|
|
|
if(
|
|
oldCacheKey &&
|
|
oldCacheKey.length > 0
|
|
){
|
|
// remove tooltip
|
|
system.toggleSystemTooltip('destroy', {});
|
|
|
|
// no user -> clear SystemBody
|
|
systemHeadExpand.velocity('stop').velocity('reverse',{
|
|
display: 'none',
|
|
complete: function(){
|
|
system.toggleBody(false, map, {});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* show/hide system body element
|
|
* @param type
|
|
* @param map
|
|
* @param callback
|
|
*/
|
|
$.fn.toggleBody = function(type, map, callback){
|
|
var system = $(this);
|
|
var systemBody = system.find('.' + config.systemBodyClass);
|
|
|
|
var systemDomId = system.attr('id');
|
|
|
|
if(type === true){
|
|
// show minimal body
|
|
systemBody.velocity({
|
|
height: config.systemBodyItemHeight + 'px'
|
|
},{
|
|
duration: 50,
|
|
display: 'auto',
|
|
progress: function(){
|
|
//revalidate element size and repaint
|
|
map.revalidate( systemDomId );
|
|
},
|
|
complete: function(){
|
|
map.revalidate( systemDomId );
|
|
|
|
if(callback.complete){
|
|
callback.complete(system);
|
|
}
|
|
}
|
|
});
|
|
}else if(type === false){
|
|
// hide body
|
|
// remove all inline styles -> possible relict from previous hover-extend
|
|
systemBody.velocity({
|
|
height: 0 + 'px',
|
|
width: '100%',
|
|
'min-width': 'none'
|
|
},{
|
|
duration: 50,
|
|
display: 'none',
|
|
begin: function(){
|
|
},
|
|
progress: function(){
|
|
// revalidate element size and repaint
|
|
map.revalidate( systemDomId );
|
|
},
|
|
complete: function(){
|
|
map.revalidate( systemDomId );
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* show/hide systems tooltip
|
|
* @param show
|
|
* @param options
|
|
*/
|
|
$.fn.toggleSystemTooltip = function(show, options){
|
|
|
|
// tooltip colors
|
|
var colorClasses = {
|
|
good: 'txt-color-green',
|
|
bad: 'txt-color-red'
|
|
};
|
|
|
|
return this.each(function(){
|
|
var system = $(this);
|
|
var tooltipId = 0;
|
|
var tooltipClassHighlight = false;
|
|
|
|
// do not update tooltips while a system is dragged
|
|
if(system.hasClass('jsPlumb_dragged')){
|
|
// skip system
|
|
return true;
|
|
}
|
|
|
|
if(show === 'destroy'){
|
|
system.tooltip( show );
|
|
system.removeAttr('data-original-title');
|
|
}else if(show === 'hide'){
|
|
system.tooltip( show );
|
|
} else if(show === 'toggle'){
|
|
system.tooltip( show );
|
|
}else if(show === 'show'){
|
|
|
|
// check if tooltip is currently visible
|
|
var tooltipActive = (system.attr('aria-describedby') !== undefined);
|
|
|
|
if(options === undefined){
|
|
options = {};
|
|
}
|
|
|
|
// optional color highlight
|
|
if(colorClasses.hasOwnProperty( options.highlight )){
|
|
tooltipClassHighlight = colorClasses[ options.highlight ];
|
|
}
|
|
|
|
if(
|
|
tooltipActive === false &&
|
|
options.id
|
|
){
|
|
|
|
// init new tooltip
|
|
tooltipId = config.systemTooltipInnerIdPrefix + options.id;
|
|
|
|
var template = '<div class="tooltip" role="tooltip">' +
|
|
'<div class="tooltip-arrow"></div>' +
|
|
'<div id="' + tooltipId + '" class="tooltip-inner txt-color ' + config.systemTooltipInnerClass + '"></div>' +
|
|
'</div>';
|
|
|
|
options.html = true;
|
|
options.animation = true;
|
|
options.template = template;
|
|
options.viewport = system.parent('.' + config.mapClass);
|
|
|
|
system.attr('title', options.title);
|
|
|
|
system.tooltip(options);
|
|
|
|
system.tooltip(show);
|
|
|
|
if(tooltipClassHighlight !== false){
|
|
// set tooltip observer and set new class after open -> due to transition effect
|
|
|
|
system.on('shown.bs.tooltip', function() {
|
|
$('#' + tooltipId).addClass( tooltipClassHighlight );
|
|
// remove observer -> color should not be changed every time a tooltip toggles e.g. dragging system
|
|
$(this).off('shown.bs.tooltip');
|
|
});
|
|
}
|
|
}else{
|
|
// update/change/toggle tooltip text or color without tooltip reload
|
|
|
|
var tooltipInner = false;
|
|
if(
|
|
options.title ||
|
|
tooltipClassHighlight !== false
|
|
){
|
|
tooltipInner = system.tooltip('fixTitle')
|
|
.data('bs.tooltip')
|
|
.$tip.find('.tooltip-inner');
|
|
|
|
if(options.title){
|
|
tooltipInner.html( options.title );
|
|
}
|
|
|
|
if(tooltipClassHighlight !== false){
|
|
tooltipInner.removeClass( colorClasses.good + ' ' + colorClasses.bad).addClass(tooltipClassHighlight);
|
|
}
|
|
}
|
|
|
|
// show() can be forced
|
|
if(options.show === true){
|
|
system.tooltip('show');
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
});
|
|
};
|
|
|
|
/**
|
|
* set or change the status of a system
|
|
* @param status
|
|
*/
|
|
$.fn.setSystemStatus = function(status){
|
|
var system = $(this);
|
|
|
|
var statusId = Util.getStatusInfoForSystem(status, 'id');
|
|
var statusClass = Util.getStatusInfoForSystem(status, 'class');
|
|
|
|
for(var property in Init.systemStatus) {
|
|
if (Init.systemStatus.hasOwnProperty(property)) {
|
|
system.removeClass( Init.systemStatus[property].class );
|
|
}
|
|
}
|
|
|
|
// add new class
|
|
system.data('statusId', statusId);
|
|
system.addClass( statusClass );
|
|
};
|
|
|
|
/**
|
|
* returns a new system or updates an existing system
|
|
* @param map
|
|
* @param data
|
|
* @returns {HTMLElement}
|
|
*/
|
|
$.fn.getSystem = function(map, data){
|
|
|
|
// get map container for mapId information
|
|
var mapContainer = $(this);
|
|
|
|
var systemId = config.systemIdPrefix + mapContainer.data('id') + '-' + data.id;
|
|
|
|
// check if system already exists
|
|
var system = document.getElementById( systemId );
|
|
|
|
var newPosX = data.position.x + 'px';
|
|
var newPosY = data.position.y + 'px';
|
|
|
|
if(!system){
|
|
|
|
// set system name or alias
|
|
var systemName = data.name;
|
|
|
|
if(
|
|
data.alias &&
|
|
data.alias !== ''
|
|
){
|
|
systemName = data.alias;
|
|
}
|
|
|
|
// get system info classes
|
|
var effectBasicClass = Util.getEffectInfoForSystem('effect', 'class');
|
|
var effectName = Util.getEffectInfoForSystem(data.effect, 'name');
|
|
var effectClass = Util.getEffectInfoForSystem(data.effect, 'class');
|
|
var secClass = Util.getSecurityClassForSystem(data.security);
|
|
|
|
system = $('<div>', {
|
|
// system
|
|
id: systemId,
|
|
class: config.systemClass
|
|
}).append(
|
|
// system head
|
|
$('<div>', {
|
|
class: config.systemHeadClass
|
|
}).append(
|
|
// System name is editable
|
|
$('<a>', {
|
|
href: '#',
|
|
class: config.systemHeadNameClass
|
|
}).attr('data-value', systemName)
|
|
).append(
|
|
// System locked status
|
|
$('<i>', {
|
|
class: ['fa', 'fa-lock', 'fa-fw'].join(' ')
|
|
}).attr('title', 'locked')
|
|
).append(
|
|
// System effect color
|
|
$('<i>', {
|
|
class: ['fa', 'fa-square ', 'fa-fw', effectBasicClass, effectClass].join(' ')
|
|
}).attr('title', effectName)
|
|
).append(
|
|
// expand option
|
|
$('<i>', {
|
|
class: ['fa', 'fa-angle-down ', config.systemHeadExpandClass].join(' ')
|
|
})
|
|
).prepend(
|
|
$('<span>', {
|
|
class: [config.systemSec, secClass].join(' '),
|
|
text: data.security
|
|
})
|
|
)
|
|
).append(
|
|
// system body
|
|
$('<div>', {
|
|
class: config.systemBodyClass
|
|
})
|
|
);
|
|
|
|
// set initial system position
|
|
system.css({
|
|
'left': newPosX,
|
|
'top': newPosY
|
|
});
|
|
|
|
}else{
|
|
system = $(system);
|
|
|
|
// set system position
|
|
var currentPosX = system.css('left');
|
|
var currentPosY = system.css('top');
|
|
|
|
if(
|
|
newPosX !== currentPosX ||
|
|
newPosY !== currentPosY
|
|
){
|
|
// change position with animation
|
|
system.velocity(
|
|
{
|
|
left: newPosX,
|
|
top: newPosY
|
|
},{
|
|
easing: 'linear',
|
|
duration: Init.animationSpeed.mapMoveSystem,
|
|
begin: function(system){
|
|
// hide system tooltip
|
|
$(system).toggleSystemTooltip('hide', {});
|
|
|
|
// move them to the "top"
|
|
$(system).updateSystemZIndex();
|
|
},
|
|
progress: function(){
|
|
map.revalidate( systemId );
|
|
},
|
|
complete: function(system){
|
|
// show tooltip
|
|
$(system).toggleSystemTooltip('show', {show: true});
|
|
|
|
map.revalidate( systemId );
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
// set system alias
|
|
var alias = system.getSystemInfo(['alias']);
|
|
|
|
if(alias !== data.alias){
|
|
// alias changed
|
|
system.find('.' + config.systemHeadNameClass).editable('setValue', data.alias);
|
|
}
|
|
}
|
|
|
|
// set system status
|
|
system.setSystemStatus(data.status.name);
|
|
system.data('id', parseInt(data.id));
|
|
system.data('systemId', parseInt(data.systemId));
|
|
system.data('name', data.name);
|
|
system.data('typeId', parseInt(data.type.id));
|
|
system.data('effect', data.effect);
|
|
system.data('security', data.security);
|
|
system.data('trueSec', parseFloat(data.trueSec));
|
|
system.data('regionId', parseInt(data.region.id));
|
|
system.data('region', data.region.name);
|
|
system.data('constellationId', parseInt(data.constellation.id));
|
|
system.data('constellation', data.constellation.name);
|
|
system.data('statics', data.statics);
|
|
system.data('updated', parseInt(data.updated.updated));
|
|
system.attr('data-mapid', parseInt(mapContainer.data('id')));
|
|
|
|
// locked system
|
|
if( Boolean( system.data( 'locked') ) !== data.locked ){
|
|
system.toggleLockSystem(false, {hideNotification: true, hideCounter: true, map: map});
|
|
}
|
|
|
|
// rally system
|
|
if( Boolean( system.data( 'rally') ) !== data.rally ){
|
|
system.toggleRallyPoint(false, {hideNotification: true, hideCounter: true});
|
|
}
|
|
|
|
return system;
|
|
};
|
|
|
|
/**
|
|
* draw a new map or update an existing map with all its systems and connections
|
|
* @param parentElement
|
|
* @param mapConfig
|
|
* @returns {*}
|
|
*/
|
|
var updateMap = function(parentElement, mapConfig){
|
|
|
|
var mapContainer = mapConfig.map.getContainer();
|
|
|
|
var newSystems = 0;
|
|
|
|
if(mapContainer === undefined){
|
|
// add new map
|
|
|
|
// create map wrapper
|
|
var mapWrapper = $('<div>', {
|
|
class: config.mapWrapperClass
|
|
});
|
|
|
|
// create new map container
|
|
mapContainer = $('<div>', {
|
|
id: config.mapIdPrefix + mapConfig.config.id,
|
|
class: [config.mapClass].join(' ')
|
|
});
|
|
|
|
// add additional information
|
|
mapContainer.data('id', mapConfig.config.id);
|
|
|
|
mapWrapper.append(mapContainer);
|
|
|
|
// append mapWrapper to parent element (at the top)
|
|
$(parentElement).prepend(mapWrapper);
|
|
|
|
// set main Container for current map -> the container exists now in DOM !! very important
|
|
mapConfig.map.setContainer( config.mapIdPrefix + mapConfig.config.id );
|
|
|
|
// set map observer
|
|
setMapObserver(mapConfig.map);
|
|
}
|
|
|
|
mapContainer = $(mapContainer);
|
|
|
|
// add additional information for this map
|
|
if(mapContainer.data('updated') !== mapConfig.config.updated){
|
|
mapContainer.data('name', mapConfig.config.name);
|
|
mapContainer.data('scopeId', mapConfig.config.scope.id);
|
|
mapContainer.data('typeId', mapConfig.config.type.id);
|
|
mapContainer.data('icon', mapConfig.config.icon);
|
|
mapContainer.data('created', mapConfig.config.created);
|
|
mapContainer.data('updated', mapConfig.config.updated);
|
|
}
|
|
|
|
|
|
// get map data
|
|
var mapData = mapContainer.getMapDataFromClient({forceData: false});
|
|
|
|
if(mapData !== false){
|
|
// map data available -> map not locked by update counter :)
|
|
|
|
var currentSystemData = mapData.data.systems;
|
|
var currentConnectionData = mapData.data.connections;
|
|
|
|
// update systems ===========================================================
|
|
for(var i = 0; i < mapConfig.data.systems.length; i++){
|
|
var systemData = mapConfig.data.systems[i];
|
|
|
|
// add system
|
|
var addNewSystem = true;
|
|
|
|
for(var k = 0; k < currentSystemData.length; k++){
|
|
if(currentSystemData[k].id === systemData.id){
|
|
if( currentSystemData[k].updated.updated < systemData.updated.updated ){
|
|
// system changed -> update
|
|
mapContainer.getSystem(mapConfig.map, systemData);
|
|
}
|
|
|
|
addNewSystem = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( addNewSystem === true){
|
|
drawSystem(mapConfig.map, systemData);
|
|
newSystems++;
|
|
}
|
|
}
|
|
|
|
// check for systems that are gone -> delete system
|
|
for(var a = 0; a < currentSystemData.length; a++){
|
|
|
|
var deleteThisSystem = true;
|
|
|
|
for(var b = 0; b < mapConfig.data.systems.length; b++){
|
|
var deleteSystemData = mapConfig.data.systems[b];
|
|
|
|
if(deleteSystemData.id === currentSystemData[a].id){
|
|
deleteThisSystem = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(deleteThisSystem === true){
|
|
var deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id);
|
|
|
|
// system not found -> delete system
|
|
removeSystem(mapConfig.map, deleteSystem);
|
|
}
|
|
}
|
|
|
|
// update connections =========================================================
|
|
|
|
// jsPlumb batch() is used, otherwise there are some "strange" visual bugs
|
|
// when switching maps (Endpoints are not displayed correctly)
|
|
mapConfig.map.batch(function() {
|
|
|
|
for(var j = 0; j < mapConfig.data.connections.length; j++){
|
|
var connectionData = mapConfig.data.connections[j];
|
|
|
|
// add connection
|
|
var addNewConnection= true;
|
|
|
|
for(var c = 0; c < currentConnectionData.length; c++){
|
|
if(
|
|
currentConnectionData[c].id === connectionData.id
|
|
){
|
|
// connection already exists -> check for updates
|
|
if(
|
|
currentConnectionData[c].updated < connectionData.updated
|
|
){
|
|
// connection changed -> update
|
|
var tempConnection = $().getConnectionById(mapData.config.id, connectionData.id);
|
|
updateConnection(tempConnection, currentConnectionData[c], connectionData);
|
|
}
|
|
|
|
addNewConnection = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(addNewConnection === true){
|
|
drawConnection(mapConfig.map, connectionData);
|
|
}
|
|
}
|
|
|
|
// check for connections that are gone -> delete connection
|
|
for(var d = 0; d < currentConnectionData.length; d++){
|
|
|
|
var deleteThisConnection = true;
|
|
|
|
for(var e = 0; e < mapConfig.data.connections.length;e++){
|
|
var deleteConnectionData = mapConfig.data.connections[e];
|
|
|
|
if(deleteConnectionData.id === currentConnectionData[d].id){
|
|
deleteThisConnection = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(deleteThisConnection === true){
|
|
// get connection from cache -> delete connection
|
|
var deleteConnection = $().getConnectionById(mapData.config.id, currentConnectionData[d].id);
|
|
|
|
if(deleteConnection){
|
|
// check if "source" and "target" still exist before remove
|
|
// this is NOT the case if the system was removed previous
|
|
if(
|
|
deleteConnection.source &&
|
|
deleteConnection.target
|
|
){
|
|
mapConfig.map.detach(deleteConnection, {fireEvent: false});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// init/update map "magnetization" feature if new systems where added
|
|
if(
|
|
config.mapMagnetizer === true &&
|
|
newSystems > 0
|
|
){
|
|
mapContainer.initMagnetizer();
|
|
}
|
|
|
|
}
|
|
|
|
return mapContainer;
|
|
};
|
|
|
|
/**
|
|
* update local connection cache
|
|
* @param mapId
|
|
* @param connection
|
|
*/
|
|
var updateConnectionCache = function(mapId, connection){
|
|
|
|
if(
|
|
mapId > 0 &&
|
|
connection
|
|
){
|
|
var connectionId = parseInt( connection.getParameter('connectionId') );
|
|
|
|
if(connectionId > 0){
|
|
connectionCache[mapId][connectionId] = connection;
|
|
}else{
|
|
console.error('updateConnectionCache', 'connectionId missing');
|
|
}
|
|
}else{
|
|
console.error('updateConnectionCache', 'missing data');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* get a connection object from "cache" (this requires the "connectionCache" cache to be actual!
|
|
* @param mapId
|
|
* @param connectionId
|
|
* @returns {*}
|
|
*/
|
|
$.fn.getConnectionById = function(mapId, connectionId){
|
|
|
|
var connection = null;
|
|
|
|
if(
|
|
connectionCache[mapId] &&
|
|
connectionCache[mapId][connectionId]
|
|
){
|
|
connection = connectionCache[mapId][connectionId];
|
|
}
|
|
|
|
return connection;
|
|
};
|
|
|
|
/**
|
|
* make all systems appear visual on the map with its connections
|
|
* @param show
|
|
* @param callback
|
|
*/
|
|
$.fn.visualizeMap = function(show, callback){
|
|
var mapElement = $(this);
|
|
|
|
// start map update counter -> prevent map updates during animations
|
|
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
var systemElements = mapElement.find('.' + config.systemClass);
|
|
var endpointElements = mapElement.find('.jsplumb-endpoint');
|
|
var connectorElements = mapElement.find('.jsplumb-connector');
|
|
var overlayElements = mapElement.find('.jsplumb-overlay, .tooltip');
|
|
|
|
// if map empty (no systems), execute callback and return
|
|
// no visual effects in IGB (glitches)
|
|
if(
|
|
systemElements.length === 0 ||
|
|
systemElements.length > 20 ||
|
|
endpointElements.length === 0 ||
|
|
CCP.isInGameBrowser() === true
|
|
){
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
// show nice animation
|
|
if(show === 'show'){
|
|
// hide elements
|
|
systemElements.css('opacity', 0);
|
|
endpointElements.css('opacity', 0);
|
|
connectorElements.css('opacity', 0);
|
|
overlayElements.css('opacity', 0);
|
|
|
|
systemElements.velocity('transition.whirlIn', {
|
|
stagger: 30,
|
|
drag: true,
|
|
duration: 100,
|
|
//display: 'auto',
|
|
complete: function(){
|
|
// show connections
|
|
endpointElements.velocity('transition.fadeIn', {
|
|
duration: 0
|
|
});
|
|
|
|
connectorElements.velocity('transition.fadeIn', {
|
|
stagger: 30,
|
|
duration: 120,
|
|
complete: function(){
|
|
callback();
|
|
}
|
|
});
|
|
|
|
// show overlay elements (if some exist)
|
|
if(overlayElements.length > 0){
|
|
overlayElements.delay(500).velocity('transition.fadeIn', {
|
|
stagger: 50,
|
|
duration: 180,
|
|
display: 'auto'
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}else if(show === 'hide'){
|
|
|
|
$('.mCSB_container').velocity('callout.shake', {
|
|
stagger: 0,
|
|
drag: false,
|
|
duration: 180,
|
|
display: 'auto'
|
|
});
|
|
|
|
overlayElements.velocity('transition.fadeOut', {
|
|
stagger: 50,
|
|
drag: true,
|
|
duration: 180,
|
|
display: 'auto'
|
|
});
|
|
|
|
endpointElements.velocity('transition.fadeOut', {
|
|
duration: 0,
|
|
display: 'block',
|
|
complete: function(){
|
|
// show connections
|
|
connectorElements.velocity('transition.fadeOut', {
|
|
stagger: 0,
|
|
drag: true,
|
|
duration: 20,
|
|
display: 'block'
|
|
});
|
|
|
|
systemElements.delay(100).velocity('transition.slideUpOut', {
|
|
stagger: 30,
|
|
drag: true,
|
|
duration: 180,
|
|
display: 'block',
|
|
complete: function(){
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* mark a system as source
|
|
* @param map
|
|
* @param system
|
|
*/
|
|
var makeSource = function(map, system){
|
|
|
|
// get scope from map defaults
|
|
var sourceConfig = globalMapConfig.source;
|
|
sourceConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes
|
|
|
|
// default connector for initial dragging a new connection
|
|
sourceConfig.connector = Util.getScopeInfoForConnection('wh', 'connectorDefinition');
|
|
|
|
map.makeSource(system, sourceConfig);
|
|
};
|
|
|
|
/**
|
|
* mark a system as target
|
|
* @param map
|
|
* @param system
|
|
*/
|
|
var makeTarget = function(map, system){
|
|
|
|
// get scope from map defaults
|
|
var targetConfig = globalMapConfig.target;
|
|
targetConfig.scope = map.Defaults.Scope; // set all allowed connections for this scopes
|
|
|
|
map.makeTarget(system, targetConfig);
|
|
};
|
|
|
|
/**
|
|
* checks if json system data is valid
|
|
* @param systemData
|
|
* @returns {boolean}
|
|
*/
|
|
var isValidSystem = function(systemData){
|
|
|
|
var isValid = true;
|
|
|
|
if(
|
|
! systemData.hasOwnProperty('name') ||
|
|
systemData.name.length === 0
|
|
){
|
|
return false;
|
|
}
|
|
|
|
return isValid;
|
|
};
|
|
|
|
/**
|
|
* draw a system with its data to a map
|
|
* @param map
|
|
* @param systemData
|
|
* @param connectedSystem
|
|
*/
|
|
var drawSystem = function(map, systemData, connectedSystem){
|
|
|
|
// check if systemData is valid
|
|
if(isValidSystem(systemData)){
|
|
var mapContainer = $(map.getContainer());
|
|
|
|
// get System Element by data
|
|
var newSystem = mapContainer.getSystem(map, systemData);
|
|
|
|
// add new system to map
|
|
mapContainer.append(newSystem);
|
|
|
|
// make new system editable
|
|
makeEditable(newSystem);
|
|
|
|
// make target
|
|
makeTarget(map, newSystem);
|
|
|
|
// make source
|
|
makeSource(map, newSystem);
|
|
|
|
// set system observer
|
|
setSystemObserver(map, newSystem);
|
|
|
|
// connect new system (if connection data is given)
|
|
if(connectedSystem){
|
|
|
|
// hint: "type" will be auto detected by jump distance
|
|
var connectionData = {
|
|
source: $(connectedSystem).data('id'),
|
|
target: newSystem.data('id'),
|
|
type: ['wh_fresh'] // default type.
|
|
};
|
|
var connection = drawConnection(map, connectionData);
|
|
|
|
// store connection
|
|
saveConnection(connection);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* delete a system with all its connections
|
|
* (ajax call) remove system from DB
|
|
* @param map
|
|
* @param systems
|
|
* @param callback function
|
|
*/
|
|
var deleteSystems = function(map, systems, callback){
|
|
|
|
var mapContainer = $( map.getContainer() );
|
|
|
|
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
var systemIds = [];
|
|
// systemIds for delete request
|
|
for(var i = 0; i < systems.length; i++){
|
|
systemIds.push( $(systems[i]).data('id') );
|
|
}
|
|
|
|
var requestData = {
|
|
systemIds: systemIds
|
|
};
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: Init.path.deleteSystem,
|
|
data: requestData,
|
|
dataType: 'json',
|
|
context: {
|
|
map: map,
|
|
systems: systems
|
|
}
|
|
}).done(function(){
|
|
// deleted SystemIds
|
|
var triggerData = {
|
|
systemIds: []
|
|
};
|
|
|
|
// remove systems from map
|
|
for(var i = 0; i < this.systems.length; i++){
|
|
var system = $(this.systems[i]);
|
|
triggerData.systemIds.push( system.data('id') );
|
|
removeSystem(this.map, system );
|
|
}
|
|
|
|
callback();
|
|
}).fail(function( jqXHR, status, error) {
|
|
var reason = status + ' ' + error;
|
|
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
|
|
$(document).setProgramStatus('problem');
|
|
});
|
|
};
|
|
|
|
/**
|
|
* remove a system from map (no backend requests)
|
|
* @param map
|
|
* @param system
|
|
*/
|
|
var removeSystem = function(map, system){
|
|
system = $(system);
|
|
|
|
// check if system is "active"
|
|
if( system.hasClass(config.systemActiveClass) ){
|
|
// get parent Tab Content and fire clear modules event
|
|
var tabContentElement = getTabContentElementByMapElement( system );
|
|
|
|
$(tabContentElement).trigger('pf:removeSystemModules');
|
|
}
|
|
|
|
// remove endpoints and their connections
|
|
// do not fire a "connectionDetached" event
|
|
map.detachAllConnections(system, {fireEvent: false});
|
|
|
|
// hide tooltip
|
|
system.toggleSystemTooltip('destroy', {});
|
|
|
|
// remove system
|
|
system.velocity('transition.whirlOut', {
|
|
duration: Init.animationSpeed.mapDeleteSystem,
|
|
complete: function(){
|
|
map.remove(this);
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* make a system name/alias editable by x-editable
|
|
* @param system
|
|
*/
|
|
var makeEditable = function(system){
|
|
system = $(system);
|
|
var headElement = $(system).find('.' + config.systemHeadNameClass);
|
|
|
|
headElement.editable({
|
|
mode: 'popup',
|
|
type: 'text',
|
|
name: 'alias',
|
|
emptytext: system.data('name'),
|
|
title: 'System alias',
|
|
placement: 'top',
|
|
onblur: 'submit',
|
|
container: 'body',
|
|
toggle: 'manual', // is triggered manually on dblClick
|
|
showbuttons: false
|
|
});
|
|
|
|
headElement.on('save', function(e, params) {
|
|
// system alias changed -> mark system as updated
|
|
system.markAsChanged();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* update z-index for a system (dragged systems should be always on top)
|
|
*/
|
|
$.fn.updateSystemZIndex = function(){
|
|
return this.each(function(){
|
|
// increase global counter
|
|
var newZIndexSystem = config.zIndexCounter++;
|
|
$(this).css('z-index', newZIndexSystem);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* get all connections of multiple systems
|
|
* @param map
|
|
* @param systems
|
|
* @returns {Array}
|
|
*/
|
|
var getConnections = function(map, systems){
|
|
|
|
var connections = [];
|
|
|
|
var withBackConnection = false;
|
|
|
|
$.each(systems, function(i, system){
|
|
// get connections where system is source
|
|
connections = connections.concat( map.getConnections({source: system}) );
|
|
|
|
if(withBackConnection === true){
|
|
// get connections where system is target
|
|
connections = connections.concat( map.getConnections({target: system}) );
|
|
}
|
|
|
|
});
|
|
|
|
return connections;
|
|
};
|
|
|
|
/**
|
|
* get all direct connections between two given systems
|
|
* @param map
|
|
* @param systemA
|
|
* @param systemB
|
|
* @returns {Array}
|
|
*/
|
|
var checkForConnection = function(map, systemA, systemB){
|
|
|
|
var connections = [];
|
|
|
|
connections = connections.concat( map.getConnections({scope: '*', source: systemA, target: systemB}) );
|
|
// get connections where system is target
|
|
connections = connections.concat( map.getConnections({scope: '*', source: systemB, target: systemA}) );
|
|
|
|
return connections;
|
|
};
|
|
|
|
/**
|
|
* connect two systems
|
|
* @param map
|
|
* @param connectionData
|
|
* @returns new connection
|
|
*/
|
|
var drawConnection = function(map, connectionData){
|
|
|
|
var mapContainer = $( map.getContainer() );
|
|
var mapId = mapContainer.data('id');
|
|
|
|
// connection id
|
|
var connectionId = 0;
|
|
if(connectionData.id){
|
|
connectionId = connectionData.id;
|
|
}
|
|
|
|
var connection = map.connect({
|
|
source: config.systemIdPrefix + mapId + '-' + connectionData.source,
|
|
target: config.systemIdPrefix + mapId + '-' + connectionData.target,
|
|
/*
|
|
parameters: {
|
|
connectionId: connectionId,
|
|
updated: connectionData.updated
|
|
},
|
|
*/
|
|
type: null
|
|
/* experimental (straight connections)
|
|
anchors: [
|
|
[ "Perimeter", { shape: 'Rectangle' }],
|
|
[ "Perimeter", { shape: 'Rectangle' }]
|
|
]
|
|
*/
|
|
});
|
|
|
|
|
|
// check if connection is valid (e.g. source/target exist
|
|
if( connection instanceof jsPlumb.Connection ){
|
|
|
|
// set connection parameters
|
|
// they should persist even through connection type change (e.g. wh -> stargate,..)
|
|
// therefore they shoule be part of the connection not of the connector
|
|
connection.setParameters({
|
|
connectionId: connectionId,
|
|
updated: connectionData.updated
|
|
});
|
|
|
|
// add connection types -----------------------------------------------------
|
|
if(connectionData.type){
|
|
for(var i = 0; i < connectionData.type.length; i++){
|
|
connection.addType(connectionData.type[i]);
|
|
}
|
|
}
|
|
|
|
// add connection scope -----------------------------------------------------
|
|
// connection have the default map Scope scope
|
|
var scope = map.Defaults.Scope;
|
|
if(connectionData.scope){
|
|
scope = connectionData.scope;
|
|
}
|
|
setConnectionScope(connection, scope);
|
|
}
|
|
|
|
// set Observer for new Connection -> is automatically set
|
|
|
|
return connection;
|
|
};
|
|
|
|
/**
|
|
* stores a connection in database
|
|
* @param connection
|
|
*/
|
|
var saveConnection = function(connection){
|
|
|
|
if( connection instanceof jsPlumb.Connection ){
|
|
|
|
var map = connection._jsPlumb.instance;
|
|
var mapContainer = $( map.getContainer() );
|
|
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
var mapId = mapContainer.data('id');
|
|
var connectionData = getDataByConnection(connection);
|
|
|
|
var requestData = {
|
|
mapData: {
|
|
id: mapId
|
|
},
|
|
connectionData: connectionData
|
|
};
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: Init.path.saveConnection,
|
|
data: requestData,
|
|
dataType: 'json',
|
|
//context: connection
|
|
context: {
|
|
connection: connection,
|
|
map: map,
|
|
mapId: mapId
|
|
}
|
|
}).done(function(newConnectionData){
|
|
|
|
if( !$.isEmptyObject(newConnectionData) ){
|
|
// update connection data e.g. "scope" has auto detected
|
|
connection = updateConnection(this.connection, connectionData, newConnectionData);
|
|
|
|
// new connection should be cached immediately!
|
|
updateConnectionCache(this.mapId, connection);
|
|
|
|
// connection scope
|
|
var scope = Util.getScopeInfoForConnection(newConnectionData.scope, 'label');
|
|
|
|
var title = 'New connection established';
|
|
if(connectionData.id > 0){
|
|
title = 'Connection switched';
|
|
}
|
|
|
|
Util.showNotify({title: title, text: 'Scope: ' + scope, type: 'success'});
|
|
}else{
|
|
// some save errors
|
|
this.map.detach(this.connection, {fireEvent: false});
|
|
}
|
|
|
|
}).fail(function( jqXHR, status, error) {
|
|
// remove this connection from map
|
|
this.map.detach(this.connection, {fireEvent: false});
|
|
|
|
var reason = status + ' ' + error;
|
|
Util.showNotify({title: jqXHR.status + ': saveConnection', text: reason, type: 'warning'});
|
|
$(document).setProgramStatus('problem');
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* delete a connection and all related data
|
|
* @param connections
|
|
* @param callback
|
|
*/
|
|
$.fn.deleteConnections = function(connections, callback){
|
|
if(connections.length > 0){
|
|
|
|
// remove connections from map
|
|
var removeConnections = function(tempConnections){
|
|
for(var i = 0; i < tempConnections.length; i++){
|
|
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
|
|
// connection is already deleted!
|
|
if(tempConnections[i]._jsPlumb){
|
|
tempConnections[i]._jsPlumb.instance.detach(tempConnections[i], {fireEvent: false});
|
|
}
|
|
}
|
|
};
|
|
|
|
// prepare delete request
|
|
var map = connections[0]._jsPlumb.instance;
|
|
var mapContainer = $( map.getContainer() );
|
|
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
var connectionIds = [];
|
|
// connectionIds for delete request
|
|
for(var i = 0; i < connections.length; i++){
|
|
var connectionId = connections[i].getParameter('connectionId');
|
|
// drag&drop a new connection does not have an id yet, if connection is not established correct
|
|
if(connectionId !== undefined){
|
|
connectionIds[i] = connections[i].getParameter('connectionId');
|
|
}
|
|
}
|
|
|
|
if(connectionIds.length > 0){
|
|
var requestData = {
|
|
connectionIds: connectionIds
|
|
};
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: Init.path.deleteConnection,
|
|
data: requestData,
|
|
dataType: 'json',
|
|
context: connections
|
|
}).done(function(data){
|
|
|
|
// remove connections from map
|
|
removeConnections(this);
|
|
|
|
// optional callback
|
|
if(callback){
|
|
callback();
|
|
}
|
|
|
|
}).fail(function( jqXHR, status, error) {
|
|
var reason = status + ' ' + error;
|
|
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
|
|
$(document).setProgramStatus('problem');
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* compares the current data and new data of a connection and updates status
|
|
* @param connection
|
|
* @param connectionData
|
|
* @param newConnectionData
|
|
* @returns {*}
|
|
*/
|
|
var updateConnection = function(connection, connectionData, newConnectionData){
|
|
|
|
var map = connection._jsPlumb.instance;
|
|
var mapContainer = $( map.getContainer() );
|
|
var mapId = mapContainer.data('id');
|
|
|
|
// check id, IDs should never change but must be set after initial save
|
|
if(connection.getParameter('connectionId') !== newConnectionData.id){
|
|
connection.setParameter('connectionId', newConnectionData.id);
|
|
}
|
|
|
|
// check scope
|
|
if(connectionData.scope !== newConnectionData.scope){
|
|
setConnectionScope(connection, newConnectionData.scope);
|
|
// for some reason the observers are gone after scope change...
|
|
setConnectionObserver(map, connection);
|
|
}
|
|
|
|
var addType = $(newConnectionData.type).not(connectionData.type).get();
|
|
var removeType = $(connectionData.type).not(newConnectionData.type).get();
|
|
|
|
// check if source or target has changed
|
|
if(connectionData.source !== newConnectionData.source ){
|
|
map.setSource(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.source);
|
|
}
|
|
if(connectionData.target !== newConnectionData.target ){
|
|
map.setTarget(connection, config.systemIdPrefix + mapId + '-' + newConnectionData.target);
|
|
}
|
|
|
|
// connection.targetId
|
|
// add types
|
|
for(var i = 0; i < addType.length; i++){
|
|
if(
|
|
addType[i].indexOf('fresh') !== -1 ||
|
|
addType[i].indexOf('reduced') !== -1 ||
|
|
addType[i].indexOf('critical') !== -1
|
|
){
|
|
setConnectionWHStatus(connection, addType[i]);
|
|
}else if( connection.hasType(addType[i]) !== true ){
|
|
// additional types e.g. eol, frig, preserve mass
|
|
connection.addType(addType[i]);
|
|
setConnectionObserver(map, connection);
|
|
}
|
|
}
|
|
|
|
// remove types
|
|
for(var j = 0; j < removeType.length; j++){
|
|
if(
|
|
removeType[j] === 'wh_eol' ||
|
|
removeType[j] === 'frigate' ||
|
|
removeType[j] === 'preserve_mass'
|
|
){
|
|
connection.removeType(removeType[j]);
|
|
setConnectionObserver(map, connection);
|
|
}
|
|
}
|
|
|
|
// set update date
|
|
connection.setParameter('updated', newConnectionData.updated);
|
|
|
|
return connection;
|
|
};
|
|
|
|
/**
|
|
* set/change connection scope
|
|
* @param connection
|
|
* @param scope
|
|
*/
|
|
var setConnectionScope = function(connection, scope){
|
|
var map = connection._jsPlumb.instance;
|
|
var currentConnector = connection.getConnector();
|
|
var newConnector = Util.getScopeInfoForConnection(scope, 'connectorDefinition');
|
|
|
|
if(currentConnector.type !== newConnector[0]){
|
|
// connector has changed
|
|
|
|
connection.setConnector( newConnector );
|
|
|
|
// remove all connection types
|
|
connection.clearTypes();
|
|
|
|
// set new new connection type
|
|
// if scope changed -> connection type == scope
|
|
connection.setType( getDefaultConnectionTypeByScope(scope) );
|
|
|
|
// change scope
|
|
connection.scope = scope;
|
|
|
|
// new observer is required after scope change
|
|
setConnectionObserver(map, connection);
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* get the default connection type for a scope
|
|
* e.g. for new type after scope change
|
|
* @param scope
|
|
* @returns {string}
|
|
*/
|
|
var getDefaultConnectionTypeByScope = function(scope){
|
|
|
|
var type = '';
|
|
switch(scope){
|
|
case 'wh':
|
|
type = 'wh_fresh';
|
|
break;
|
|
case 'jumpbridge':
|
|
type = 'jumpbridge';
|
|
break;
|
|
case'stargate':
|
|
type = 'stargate';
|
|
break;
|
|
}
|
|
|
|
return type;
|
|
};
|
|
|
|
/**
|
|
* set/change connection status of a wormhole
|
|
* @param connection
|
|
* @param status
|
|
*/
|
|
var setConnectionWHStatus = function(connection, status){
|
|
|
|
if(
|
|
status === 'wh_fresh' &&
|
|
connection.hasType('wh_fresh') !== true
|
|
){
|
|
connection.removeType('wh_reduced');
|
|
connection.removeType('wh_critical');
|
|
connection.addType('wh_fresh');
|
|
}else if(
|
|
status === 'wh_reduced' &&
|
|
connection.hasType('wh_reduced') !== true
|
|
){
|
|
connection.removeType('wh_fresh');
|
|
connection.removeType('wh_critical');
|
|
connection.addType('wh_reduced');
|
|
}else if(
|
|
status === 'wh_critical' &&
|
|
connection.hasType('wh_critical') !== true
|
|
){
|
|
connection.removeType('wh_fresh');
|
|
connection.removeType('wh_reduced');
|
|
connection.addType('wh_critical');
|
|
}else if(
|
|
status === 'wh_eol' &&
|
|
connection.hasType('wh_eol') !== true
|
|
){
|
|
connection.addType('wh_eol');
|
|
}else if(
|
|
status === 'wh_eol' &&
|
|
connection.hasType('wh_eol') !== true
|
|
){
|
|
connection.addType('wh_eol');
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* load context menu template for map
|
|
*/
|
|
var initMapContextMenu = function(){
|
|
|
|
var moduleConfig = {
|
|
name: 'modules/contextmenu',
|
|
position: $('#' + config.dynamicElementWrapperId)
|
|
};
|
|
|
|
var moduleData = {
|
|
id: config.mapContextMenuId,
|
|
items: [
|
|
{icon: 'fa-info', action: 'info', text: 'info'},
|
|
{icon: 'fa-plus', action: 'add_system', text: 'add system'},
|
|
{icon: 'fa-object-ungroup', action: 'select_all', text: 'select all'},
|
|
{icon: 'fa-filter', action: 'filter_scope', text: 'filter scope', subitems: [
|
|
{subIcon: '', subAction: 'filter_wh', subText: 'wormhole'},
|
|
{subIcon: '', subAction: 'filter_stargate', subText: 'stargate'},
|
|
{subIcon: '', subAction: 'filter_jumpbridge', subText: 'jumpbridge'}
|
|
]},
|
|
{divider: true, action: 'delete_systems'},
|
|
{icon: 'fa-eraser', action: 'delete_systems', text: 'delete systems'}
|
|
]
|
|
};
|
|
|
|
Render.showModule(moduleConfig, moduleData);
|
|
};
|
|
|
|
/**
|
|
* load contextmenu template for connections
|
|
*/
|
|
var initConnectionContextMenu = function(){
|
|
|
|
var moduleConfig = {
|
|
name: 'modules/contextmenu',
|
|
position: $('#' + config.dynamicElementWrapperId)
|
|
};
|
|
|
|
var moduleData = {
|
|
id: config.connectionContextMenuId,
|
|
items: [
|
|
{icon: 'fa-plane', action: 'frigate', text: 'frigate hole'},
|
|
{icon: 'fa-warning', 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: 'change status', subitems: [
|
|
{subIcon: 'fa-clock-o', subAction: 'wh_eol', subText: 'toggle EOL'},
|
|
{subDivider: true},
|
|
{subIcon: 'fa-circle', subAction: 'status_fresh', subText: 'stage 0 (fresh)'},
|
|
{subIcon: 'fa-adjust', subAction: 'status_reduced', subText: 'stage 1 (reduced)'},
|
|
{subIcon: 'fa-circle-o', subAction: 'status_critical', subText: 'stage 2 (critical)'}
|
|
|
|
]},
|
|
{divider: true, action: 'delete_connection'},
|
|
{icon: 'fa-eraser', action: 'delete_connection', text: 'delete'}
|
|
]
|
|
};
|
|
|
|
Render.showModule(moduleConfig, moduleData);
|
|
|
|
};
|
|
|
|
/**
|
|
* load contextmenu template for systems
|
|
*/
|
|
var initSystemContextMenu = function(){
|
|
|
|
var systemStatus = [];
|
|
$.each(Init.systemStatus, function(status, statusData){
|
|
var tempStatus = {
|
|
subIcon: 'fa-tag',
|
|
subIconClass: statusData.class,
|
|
subAction: 'change_status_' + status,
|
|
subText: statusData.label
|
|
};
|
|
systemStatus.push(tempStatus);
|
|
});
|
|
|
|
var moduleConfig = {
|
|
name: 'modules/contextmenu',
|
|
position: $('#' + config.dynamicElementWrapperId)
|
|
};
|
|
|
|
var moduleData = {
|
|
id: config.systemContextMenuId,
|
|
items: [
|
|
{icon: 'fa-plus', action: 'add_system', text: 'add system'},
|
|
{icon: 'fa-lock', action: 'lock_system', text: 'lock system'},
|
|
{icon: 'fa-users', action: 'set_rally', text: 'set rally point'},
|
|
{icon: 'fa-tags', text: 'set status', subitems: systemStatus},
|
|
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
|
|
{subIcon: 'fa-flag-checkered', subAction: 'set_destination', subText: 'set destination'},
|
|
{subDivider: true, action: ''},
|
|
{subIcon: 'fa-step-backward', subAction: 'add_first_waypoint', subText: 'add new [start]'},
|
|
{subIcon: 'fa-step-forward', subAction: 'add_last_waypoint', subText: 'add new [end]'}
|
|
]},
|
|
{divider: true, action: 'ingame'},
|
|
{icon: 'fa-reply fa-rotate-180', action: 'ingame', text: 'ingame', subitems: [
|
|
{subIcon: 'fa-info', subAction: 'ingame_show_info', subText: 'show info'}
|
|
]},
|
|
{divider: true, action: 'delete_system'},
|
|
{icon: 'fa-eraser', action: 'delete_system', text: 'delete system'}
|
|
]
|
|
};
|
|
|
|
Render.showModule(moduleConfig, moduleData);
|
|
|
|
};
|
|
|
|
/**
|
|
* set up all actions that can be preformed on a system
|
|
* @param map
|
|
* @param system
|
|
*/
|
|
var setSystemObserver = function(map, system){
|
|
|
|
system = $(system);
|
|
|
|
|
|
// get map container
|
|
var mapContainer = $( map.getContainer() );
|
|
var systemHeadExpand = $( system.find('.' + config.systemHeadExpandClass) );
|
|
var systemBody = $( system.find('.' + config.systemBodyClass) );
|
|
|
|
// map overlay will be set on "drag" start
|
|
var mapOverlayTimer = null;
|
|
|
|
// make system draggable
|
|
map.draggable(system, {
|
|
containment: 'parent',
|
|
constrain: true,
|
|
//scroll: true, // not working because of customized scrollbar
|
|
filter: '.' + config.systemHeadNameClass, // disable drag on "system name"
|
|
snapThreshold: config.mapSnapToGridDimension, // distance for grid snapping "magnet" effect (optional)
|
|
start: function(params, a, b){
|
|
var dragSystem = $(params.el);
|
|
|
|
mapOverlayTimer = dragSystem.getMapOverlay('timer');
|
|
|
|
// start map update timer
|
|
mapOverlayTimer.startMapUpdateCounter();
|
|
|
|
// check if grid-snap is enable
|
|
if(config.mapSnapToGrid){
|
|
params.drag.params.grid = [config.mapSnapToGridDimension, config.mapSnapToGridDimension];
|
|
}else{
|
|
delete( params.drag.params.grid );
|
|
}
|
|
|
|
// stop "system click event" right after drop event is finished
|
|
dragSystem.addClass('no-click');
|
|
|
|
// drag system is not always selected
|
|
var selectedSystems = mapContainer.getSelectedSystems().get();
|
|
selectedSystems = selectedSystems.concat( dragSystem.get() );
|
|
selectedSystems = $.unique( selectedSystems );
|
|
|
|
// hide tooltip
|
|
$(selectedSystems).toggleSystemTooltip('hide', {});
|
|
|
|
// move them to the "top"
|
|
$(selectedSystems).updateSystemZIndex();
|
|
},
|
|
drag: function(p){
|
|
// start map update timer
|
|
mapOverlayTimer.startMapUpdateCounter();
|
|
|
|
// 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);
|
|
},
|
|
stop: function(params){
|
|
var dragSystem = $(params.el);
|
|
|
|
// start map update timer
|
|
mapOverlayTimer.startMapUpdateCounter();
|
|
|
|
setTimeout(function(){
|
|
dragSystem.removeClass('no-click');
|
|
}, Init.timer.DBL_CLICK + 50);
|
|
|
|
// show tooltip
|
|
dragSystem.toggleSystemTooltip('show', {show: true});
|
|
|
|
// mark as "changed"
|
|
dragSystem.markAsChanged();
|
|
|
|
// set new position for popover edit field (system name)
|
|
var newPosition = dragSystem.position();
|
|
|
|
var placement = 'top';
|
|
if(newPosition.top < 100){
|
|
placement = 'bottom';
|
|
}
|
|
if(newPosition.left < 100){
|
|
placement = 'right';
|
|
}
|
|
dragSystem.find('.' + config.systemHeadNameClass).editable('option', 'placement', placement);
|
|
|
|
// drag system is not always selected
|
|
var selectedSystems = mapContainer.getSelectedSystems().get();
|
|
selectedSystems = selectedSystems.concat( dragSystem.get() );
|
|
selectedSystems = $.unique( selectedSystems );
|
|
|
|
for(var i = 0; i < selectedSystems.length; i++){
|
|
var tempSystem = $(selectedSystems[i]);
|
|
// repaint connections -> just in case something fails...
|
|
map.revalidate( tempSystem.attr('id') );
|
|
}
|
|
}
|
|
});
|
|
|
|
if(system.data('locked') === true){
|
|
map.setDraggable(system, false);
|
|
}
|
|
|
|
// init system tooltips =============================================================================
|
|
var systemTooltipOptions = {
|
|
toggle: 'tooltip',
|
|
placement: 'right',
|
|
container: 'body',
|
|
viewport: system.id
|
|
};
|
|
|
|
system.find('.fa').tooltip(systemTooltipOptions);
|
|
|
|
// init system body expand ==========================================================================
|
|
systemHeadExpand.hoverIntent(function(e){
|
|
// hover in
|
|
var hoverSystem = $(this).parents('.' + config.systemClass);
|
|
var hoverSystemId = hoverSystem.attr('id');
|
|
|
|
// get ship counter and calculate expand height
|
|
var userCount = parseInt( hoverSystem.data('userCount') );
|
|
|
|
var expandHeight = userCount * config.systemBodyItemHeight;
|
|
|
|
systemBody.velocity('stop').velocity(
|
|
{
|
|
height: expandHeight + 'px',
|
|
width: 150,
|
|
'min-width': '150px'
|
|
},{
|
|
easing: 'easeInOutQuart',
|
|
duration: 150,
|
|
progress: function(){
|
|
// repaint connections of current system
|
|
map.revalidate( hoverSystemId );
|
|
},
|
|
complete: function(){
|
|
map.revalidate( hoverSystemId );
|
|
|
|
// extend player name element
|
|
$(this).find('.' + config.systemBodyItemNameClass).css({width: '80px'});
|
|
|
|
$(this).find('.' + config.systemBodyRightClass).velocity('stop').velocity({
|
|
opacity: 1
|
|
},{
|
|
duration: 150,
|
|
display: 'auto'
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
}, function(e){
|
|
// hover out
|
|
var hoverSystem = $(this).parents('.' + config.systemClass);
|
|
var hoverSystemId = hoverSystem.attr('id');
|
|
|
|
// stop animation (prevent visual bug if user spams hover-icon [in - out])
|
|
systemBody.velocity('stop');
|
|
|
|
// reduce player name element back to "normal" size (css class width is used)
|
|
systemBody.find('.' + config.systemBodyItemNameClass).css({width: ''});
|
|
|
|
systemBody.find('.' + config.systemBodyRightClass).velocity('stop').velocity( {
|
|
opacity: 0,
|
|
'min-width': '0px'
|
|
},{
|
|
easing: 'easeInOutQuart',
|
|
duration: 150,
|
|
display: 'none',
|
|
complete: function(){
|
|
systemBody.velocity('stop').velocity('reverse', {
|
|
complete: function(){
|
|
// overwrite "complete" function from first "hover"-open
|
|
map.revalidate( hoverSystemId );
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
// context menu =====================================================================================
|
|
|
|
// trigger context menu
|
|
system.off('contextmenu').on('contextmenu', function(e){
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
var systemElement = $(this);
|
|
|
|
// hide all map contextmenu options
|
|
var hideOptions = getHiddenContextMenuOptions(systemElement);
|
|
|
|
var activeOptions = getActiveContextMenuOptions(systemElement);
|
|
|
|
$(e.target).trigger('pf:openContextMenu', [e, this, hideOptions, activeOptions]);
|
|
return false;
|
|
});
|
|
|
|
// init context menu
|
|
system.contextMenu({
|
|
menuSelector: "#" + config.systemContextMenuId,
|
|
menuSelected: function (params) {
|
|
|
|
// click action
|
|
var action = params.selectedMenu.attr('data-action');
|
|
|
|
// current system
|
|
var currentSystem = $(params.component);
|
|
|
|
// system name
|
|
var currentSystemName = currentSystem.getSystemInfo( ['alias'] );
|
|
|
|
var systemData = {};
|
|
|
|
switch(action){
|
|
case 'add_system':
|
|
// add a new system
|
|
showNewSystemDialog(map, {sourceSystem: currentSystem} );
|
|
|
|
break;
|
|
case 'lock_system':
|
|
// lock system
|
|
currentSystem.toggleLockSystem(true, {map: map});
|
|
|
|
// repaint connections, -> system changed its size!
|
|
map.repaint( currentSystem );
|
|
|
|
currentSystem.markAsChanged();
|
|
break;
|
|
case 'set_rally':
|
|
// set rally point
|
|
if( ! currentSystem.data( 'rally' ) ){
|
|
|
|
// show confirm dialog
|
|
var rallyDialog = bootbox.dialog({
|
|
message: 'Do you want to poke active pilots?',
|
|
title: 'Set rally point for system "' + currentSystemName + '"',
|
|
buttons: {
|
|
close: {
|
|
label: 'cancel',
|
|
className: 'btn-default',
|
|
callback: function(){
|
|
$(rallyDialog).modal('hide');
|
|
}
|
|
},
|
|
setRallyPoke: {
|
|
label: '<i class="fa fa-fw fa-bullhorn"></i> Set rally and poke',
|
|
className: 'btn-primary',
|
|
callback: function() {
|
|
currentSystem.toggleRallyPoint(true, {});
|
|
currentSystem.markAsChanged();
|
|
}
|
|
},
|
|
success: {
|
|
label: '<i class="fa fa-fw fa-check"></i> save',
|
|
className: 'btn-success',
|
|
callback: function() {
|
|
currentSystem.toggleRallyPoint(false, {});
|
|
currentSystem.markAsChanged();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}else{
|
|
// remove rally point
|
|
currentSystem.toggleRallyPoint(false, {});
|
|
currentSystem.markAsChanged();
|
|
}
|
|
break;
|
|
case 'change_status_unknown':
|
|
case 'change_status_friendly':
|
|
case 'change_status_occupied':
|
|
case 'change_status_hostile':
|
|
case 'change_status_empty':
|
|
case 'change_status_unscanned':
|
|
// change system status
|
|
currentSystem.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
var statusString = action.split('_');
|
|
|
|
currentSystem.setSystemStatus(statusString[2]);
|
|
|
|
currentSystem.markAsChanged();
|
|
break;
|
|
case 'delete_system':
|
|
// confirm dialog
|
|
bootbox.confirm('Delete system and all its connections?', function(result) {
|
|
if(result){
|
|
var systemName = currentSystem.getSystemInfo(['alias']);
|
|
deleteSystems(map, [currentSystem], function(){
|
|
// callback function after delete -> close dialog
|
|
bootbox.hideAll();
|
|
Util.showNotify({title: 'System deleted', text: systemName, type: 'success'});
|
|
});
|
|
|
|
return false;
|
|
}
|
|
});
|
|
break;
|
|
case 'ingame_show_info':
|
|
systemData = system.getSystemData();
|
|
|
|
CCPEVE.showInfo(5, systemData.systemId );
|
|
break;
|
|
case 'set_destination':
|
|
case 'add_first_waypoint':
|
|
case 'add_last_waypoint':
|
|
systemData = system.getSystemData();
|
|
setDestination(systemData, action);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
|
|
// system click events ==============================================================================
|
|
var double = function(e){
|
|
var system = $(this);
|
|
var headElement = $(system).find('.' + config.systemHeadNameClass);
|
|
|
|
// update z-index for system, editable field should be on top
|
|
// move them to the "top"
|
|
$(system).updateSystemZIndex();
|
|
|
|
// show "set alias" input (x-editable)
|
|
headElement.editable('show');
|
|
};
|
|
|
|
var single = function(e){
|
|
|
|
// check if click was performed on "popover" (x-editable)
|
|
var popoverClick = false;
|
|
if( $(e.target).parents('.popover').length ){
|
|
popoverClick = true;
|
|
}
|
|
|
|
// continue if click was *not* on a popover dialog of a system
|
|
if( !popoverClick ){
|
|
var system = $(this);
|
|
|
|
// check if system is locked for "click" events
|
|
if( !system.hasClass('no-click') ){
|
|
// left mouse button
|
|
if(e.which === 1){
|
|
if(! system.hasClass('no-click')){
|
|
if(e.ctrlKey === true){
|
|
// select system
|
|
system.toggleSelectSystem(map);
|
|
}else{
|
|
system.showSystemInfo(map);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
system.singleDoubleClick(single, double);
|
|
};
|
|
|
|
|
|
/**
|
|
* set new destination for a system
|
|
* -> CREST request
|
|
* @param systemData
|
|
* @param type
|
|
*/
|
|
var setDestination = function(systemData, type){
|
|
|
|
var description = '';
|
|
switch(type){
|
|
case 'set_destination':
|
|
description = 'Set destination';
|
|
break;
|
|
case 'add_first_waypoint':
|
|
description = 'Set first waypoint';
|
|
break;
|
|
case 'add_last_waypoint':
|
|
description = 'Set new waypoint';
|
|
break;
|
|
}
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: Init.path.setDestination,
|
|
data: {
|
|
clearOtherWaypoints: (type === 'set_destination') ? 1 : 0,
|
|
first: (type === 'add_last_waypoint') ? 0 : 1,
|
|
systemData: [{
|
|
systemId: systemData.systemId,
|
|
name: systemData.name
|
|
}]
|
|
},
|
|
context: {
|
|
description: description
|
|
},
|
|
dataType: 'json'
|
|
}).done(function(responseData){
|
|
if(
|
|
responseData.systemData &&
|
|
responseData.systemData.length > 0
|
|
){
|
|
for (var j = 0; j < responseData.systemData.length; j++) {
|
|
Util.showNotify({title: this.description, text: 'System: ' + responseData.systemData[j].name, type: 'success'});
|
|
}
|
|
}
|
|
|
|
if(
|
|
responseData.error &&
|
|
responseData.error.length > 0
|
|
){
|
|
for(var i = 0; i < responseData.error.length; i++){
|
|
Util.showNotify({title: this.description + ' error', text: 'System: ' + responseData.error[i].message, type: 'error'});
|
|
}
|
|
}
|
|
|
|
}).fail(function( jqXHR, status, error) {
|
|
var reason = status + ' ' + error;
|
|
Util.showNotify({title: jqXHR.status + ': ' + this.description, text: reason, type: 'warning'});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* mark a dom element (map, system, connection) as changed
|
|
*/
|
|
$.fn.markAsChanged = function(){
|
|
return this.each(function(){
|
|
var element = $(this);
|
|
|
|
if( element.hasClass(config.systemClass) ){
|
|
// system element
|
|
element.data('updated', 0);
|
|
}else{
|
|
// connection element
|
|
this.setParameter('updated', 0);
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* check if an dom element (system, connection) has changed
|
|
* @returns {boolean}
|
|
*/
|
|
$.fn.hasChanged = function(){
|
|
var element = $(this);
|
|
var changed = false;
|
|
|
|
if( element.hasClass(config.systemClass) ){
|
|
// system element
|
|
changed = (element.data('updated') === 0);
|
|
}else{
|
|
// connection element
|
|
changed = (this[0].getParameter('updated') === 0);
|
|
}
|
|
|
|
return changed;
|
|
};
|
|
|
|
/**
|
|
* triggers the "showSystemInfo" event, that is responsible for initializing the "map info" panel
|
|
* @param map
|
|
*/
|
|
$.fn.showSystemInfo = function(map){
|
|
var system = $(this);
|
|
|
|
// activate system
|
|
markSystemActive(map, system);
|
|
|
|
// get parent Tab Content and fire update event
|
|
var tabContentElement = getTabContentElementByMapElement( system );
|
|
|
|
// collect all required data from map module to update the info element
|
|
// store them global and assessable for each module
|
|
var currentSystemData = {
|
|
systemData: system.getSystemData(),
|
|
mapId: parseInt( system.attr('data-mapid') )
|
|
};
|
|
|
|
Util.setCurrentSystemData(currentSystemData);
|
|
|
|
$(tabContentElement).trigger('pf:drawSystemModules');
|
|
};
|
|
|
|
/**
|
|
* toggle selectable status of a system
|
|
*/
|
|
$.fn.toggleSelectSystem = function(map){
|
|
|
|
return this.each(function(){
|
|
var system = $(this);
|
|
|
|
if( system.data('locked') !== true ){
|
|
|
|
if( system.hasClass( config.systemSelectedClass ) ){
|
|
system.removeClass( config.systemSelectedClass );
|
|
|
|
map.removeFromDragSelection(system);
|
|
}else{
|
|
system.addClass( config.systemSelectedClass );
|
|
map.addToDragSelection(system);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* get all selected (NOT active) systems in a map
|
|
* @returns {*}
|
|
*/
|
|
$.fn.getSelectedSystems = function(){
|
|
var mapElement = $(this);
|
|
return mapElement.find('.' + config.systemSelectedClass);
|
|
};
|
|
|
|
/**
|
|
* toggle log status of a system
|
|
* @param poke
|
|
* @param options
|
|
*/
|
|
$.fn.toggleLockSystem = function(poke, options){
|
|
|
|
var system = $(this);
|
|
|
|
var map = options.map;
|
|
|
|
var hideNotification = false;
|
|
if(options.hideNotification === true){
|
|
hideNotification = true;
|
|
}
|
|
|
|
var hideCounter = false;
|
|
if(options.hideCounter === true){
|
|
hideCounter = true;
|
|
}
|
|
|
|
var systemName = system.getSystemInfo( ['alias'] );
|
|
|
|
if( system.data( 'locked' ) === true ){
|
|
system.data('locked', false);
|
|
system.removeClass( config.systemLockedClass );
|
|
|
|
// enable draggable
|
|
map.setDraggable(system, true);
|
|
|
|
if(! hideNotification){
|
|
Util.showNotify({title: 'System unlocked', text: systemName, type: 'unlock'});
|
|
}
|
|
}else{
|
|
system.data('locked', true);
|
|
system.addClass( config.systemLockedClass );
|
|
|
|
// enable draggable
|
|
map.setDraggable(system, false);
|
|
|
|
if(! hideNotification){
|
|
Util.showNotify({title: 'System locked', text: systemName, type: 'lock'});
|
|
}
|
|
}
|
|
|
|
// repaint connections
|
|
map.revalidate( system.attr('id') );
|
|
|
|
|
|
if(! hideCounter){
|
|
$(system).getMapOverlay('timer').startMapUpdateCounter();
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* toggle a system as rally point and display notifications
|
|
* @param poke
|
|
* @param options
|
|
*/
|
|
$.fn.toggleRallyPoint = function(poke, options){
|
|
|
|
var system = $(this);
|
|
|
|
var rallyClass = Util.getInfoForSystem('rally', 'class');
|
|
|
|
var hideNotification = false;
|
|
if(options.hideNotification === true){
|
|
hideNotification = true;
|
|
}
|
|
|
|
var hideCounter = false;
|
|
if(options.hideCounter === true){
|
|
hideCounter = true;
|
|
}
|
|
|
|
// check of system is already marked as rally
|
|
if( system.data( 'rally' ) === true ){
|
|
system.removeClass( rallyClass );
|
|
system.data( 'rally', false );
|
|
|
|
if(! hideNotification){
|
|
Util.showNotify({title: 'Rally point removed', type: 'success'});
|
|
}
|
|
}else{
|
|
system.addClass( rallyClass );
|
|
system.data( 'rally', true );
|
|
|
|
if(! hideNotification){
|
|
var systemName = system.getSystemInfo( ['alias'] );
|
|
|
|
var notificationOptions = {
|
|
title: 'Rally Point',
|
|
text: 'System: ' + systemName,
|
|
type: 'success'
|
|
};
|
|
|
|
if(poke === true){
|
|
// desktop poke
|
|
Util.showNotify(notificationOptions, {desktop: true, stack: 'barBottom'});
|
|
}else{
|
|
Util.showNotify(notificationOptions, {stack: 'barBottom'});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(! hideCounter){
|
|
$(system).getMapOverlay('timer').startMapUpdateCounter();
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* get TabContentElement by any element on a map e.g. system
|
|
* @param element
|
|
* @returns {*}
|
|
*/
|
|
var getTabContentElementByMapElement = function(element){
|
|
var tabContentElement = $(element).parents('.' + config.mapTabContentClass);
|
|
return tabContentElement;
|
|
};
|
|
|
|
/**
|
|
* set observer for a map container
|
|
* @param map
|
|
*/
|
|
var setMapObserver = function(map){
|
|
|
|
// get map container
|
|
var mapContainer = map.getContainer();
|
|
|
|
$(mapContainer).bind('contextmenu', function(e){
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
// make sure map is clicked and NOT a connection
|
|
if($(e.target).hasClass( config.mapClass )){
|
|
var mapElement = $(this);
|
|
|
|
var hideOptions = getHiddenContextMenuOptions(mapElement);
|
|
|
|
var activeOptions = getActiveContextMenuOptions(mapElement);
|
|
|
|
$(e.target).trigger('pf:openContextMenu', [e, mapElement, hideOptions, activeOptions]);
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
$(mapContainer).contextMenu({
|
|
menuSelector: "#" + config.mapContextMenuId,
|
|
menuSelected: function (params) {
|
|
|
|
// click action
|
|
var action = params.selectedMenu.attr('data-action');
|
|
|
|
// current map
|
|
var currentMapElement = $(params.component);
|
|
|
|
var currentMapId = parseInt( currentMapElement.data('id') );
|
|
|
|
// get map instance
|
|
var currentMap = getMapInstance(currentMapId);
|
|
|
|
// click position
|
|
var position = params.position;
|
|
|
|
switch(action){
|
|
case 'add_system':
|
|
// add new system dialog
|
|
showNewSystemDialog(currentMap, {position: position});
|
|
break;
|
|
case 'select_all':
|
|
|
|
var allSystems = currentMapElement.find('.' + config.systemClass + ':not(.' + config.systemSelectedClass + ')');
|
|
|
|
// filter non-locked systems
|
|
allSystems = allSystems.filter(function(i, el){
|
|
return ( $(el).data('locked') !== true );
|
|
});
|
|
|
|
allSystems.toggleSelectSystem(currentMap);
|
|
|
|
Util.showNotify({title: allSystems.length + ' systems selected', type: 'success'});
|
|
break;
|
|
case 'filter_wh':
|
|
case 'filter_stargate':
|
|
case 'filter_jumpbridge':
|
|
// filter (show/hide)
|
|
var filterScope = action.split('_')[1];
|
|
|
|
// scope label
|
|
var filterScopeLabel = Util.getScopeInfoForMap(filterScope, 'label');
|
|
|
|
var showScope = true;
|
|
if(
|
|
currentMapElement.data('filter_scope') &&
|
|
currentMapElement.data('filter_scope') === filterScope
|
|
){
|
|
// remove scope filter
|
|
currentMapElement.data('filter_scope', false);
|
|
showScope = false;
|
|
|
|
// hide map overlay filter info
|
|
currentMapElement.getMapOverlay('info').updateOverlayIcon('filter', 'hide');
|
|
}else{
|
|
// set scope filter
|
|
currentMapElement.data('filter_scope', filterScope);
|
|
|
|
// show map overlay filter info
|
|
currentMapElement.getMapOverlay('info').updateOverlayIcon('filter', 'show');
|
|
}
|
|
|
|
var filteredConnections = currentMap.getAllConnections(filterScope);
|
|
|
|
for(var i = 0; i < filteredConnections.length; i++){
|
|
var tempConnection = filteredConnections[i];
|
|
|
|
var tempEndpoints = tempConnection.endpoints;
|
|
var setVisible = true;
|
|
|
|
if(
|
|
showScope &&
|
|
tempConnection.scope !== filterScope
|
|
){
|
|
setVisible = false;
|
|
}
|
|
|
|
|
|
for(var j = 0; j < tempEndpoints.length; j++){
|
|
tempEndpoints[j].setVisible( setVisible );
|
|
}
|
|
}
|
|
|
|
Util.showNotify({title: 'Scope filter changed', text: filterScopeLabel, type: 'success'});
|
|
|
|
break;
|
|
case 'delete_systems':
|
|
// delete all selected systems with its connections
|
|
var selectedSystems = $(currentMapElement).getSelectedSystems();
|
|
|
|
if(selectedSystems.length > 0){
|
|
var systemDeleteDialog = bootbox.confirm('Delete ' + selectedSystems.length + ' selected systems and its connections?', function(result) {
|
|
if(result){
|
|
currentMapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
deleteSystems(currentMap, selectedSystems, function(){
|
|
// callback function after delete -> close dialog
|
|
|
|
$(systemDeleteDialog).modal('hide');
|
|
Util.showNotify({title: selectedSystems.length + ' systems deleted', type: 'success'});
|
|
});
|
|
}
|
|
});
|
|
}else{
|
|
Util.showNotify({title: 'No systems selected', type: 'error'});
|
|
}
|
|
|
|
break;
|
|
case 'info':
|
|
// open map info dialog
|
|
$(document).triggerMenuEvent('ShowMapInfo');
|
|
break;
|
|
|
|
}
|
|
}
|
|
});
|
|
|
|
// init drag-frame selection
|
|
$(mapContainer).dragToSelect({
|
|
selectables: '.' + config.systemClass,
|
|
onHide: function (selectBox, deselectedSystems) {
|
|
var selectedSystems = $(mapContainer).getSelectedSystems();
|
|
|
|
if(selectedSystems.length > 0){
|
|
// make all selected systems draggable
|
|
Util.showNotify({title: selectedSystems.length + ' systems selected', type: 'success'});
|
|
|
|
// convert former group draggable systems so single draggable
|
|
for(var i = 0; i < selectedSystems.length; i++){
|
|
map.addToDragSelection( selectedSystems[i] );
|
|
}
|
|
}
|
|
|
|
// convert former group draggable systems so single draggable
|
|
for(var j = 0; j < deselectedSystems.length; j++){
|
|
map.removeFromDragSelection( deselectedSystems[j] );
|
|
}
|
|
|
|
},
|
|
onShow: function(){
|
|
$(document).trigger('pf:closeMenu', [{}]);
|
|
},
|
|
onRefresh: function(){
|
|
}
|
|
});
|
|
|
|
// catch events =========================================================
|
|
|
|
// toggle global map option (e.g. "grid snap", "magnetization"
|
|
$(mapContainer).on('pf:menuMapOption', function(e, data){
|
|
|
|
var currentMapElement = $(this);
|
|
|
|
// toggle map option
|
|
config[data.option] = !config[data.option];
|
|
|
|
// toggle map class (e.g. for grid)
|
|
if(data.class){
|
|
currentMapElement.toggleClass( config[data.class] );
|
|
}
|
|
|
|
// toggle button class
|
|
$(data.button).toggleClass('active');
|
|
|
|
var notificationText = 'disabled';
|
|
if( config[data.option] ){
|
|
|
|
// call optional jQuery extension on mapElement
|
|
if(data.onEnable){
|
|
$.fn[ data.onEnable ].apply( currentMapElement );
|
|
}
|
|
|
|
// show map overlay info icon
|
|
notificationText = 'enabled';
|
|
currentMapElement.getMapOverlay('info').updateOverlayIcon(data.option, 'show');
|
|
}else{
|
|
// call optional jQuery extension on mapElement
|
|
if(data.onDisable){
|
|
$.fn[ data.onDisable ].apply( currentMapElement );
|
|
}
|
|
|
|
// hide map overlay info icon
|
|
currentMapElement.getMapOverlay('info').updateOverlayIcon(data.option, 'hide');
|
|
}
|
|
|
|
Util.showNotify({title: data.description, text: notificationText, type: 'info'});
|
|
});
|
|
|
|
// delete system event
|
|
// triggered from "map info" dialog scope
|
|
$(mapContainer).on('pf:deleteSystems', function(e, data){
|
|
deleteSystems(map, data.systems, data.callback);
|
|
});
|
|
|
|
$(mapContainer).on('pf:menuSelectSystem', function(e, data){
|
|
var tempMapContainer = $(this);
|
|
var systemId = config.systemIdPrefix + tempMapContainer.data('id') + '-' + data.systemId;
|
|
var system = $(this).find('#' + systemId);
|
|
|
|
if(system.length === 1){
|
|
// scroll to system
|
|
var tempMapWrapper = tempMapContainer.parents('.' + config.mapWrapperClass);
|
|
tempMapWrapper.scrollTo(system);
|
|
|
|
// select system
|
|
system.showSystemInfo(map);
|
|
}
|
|
});
|
|
|
|
|
|
};
|
|
|
|
/**
|
|
* get hidden menu entry options for a context menu
|
|
* @param component
|
|
* @returns {Array}
|
|
*/
|
|
var getHiddenContextMenuOptions = function(component){
|
|
|
|
var hiddenOptions = [];
|
|
|
|
if(component instanceof jsPlumb.Connection){
|
|
// disable connection menu entries
|
|
|
|
var scope = component.scope;
|
|
|
|
if(scope === 'stargate'){
|
|
hiddenOptions.push('frigate');
|
|
hiddenOptions.push('preserve_mass');
|
|
hiddenOptions.push('change_status');
|
|
|
|
hiddenOptions.push('scope_stargate');
|
|
}else if(scope === 'jumpbridge'){
|
|
hiddenOptions.push('frigate');
|
|
hiddenOptions.push('preserve_mass');
|
|
hiddenOptions.push('change_status');
|
|
hiddenOptions.push('scope_jumpbridge');
|
|
}else if(scope === 'wh'){
|
|
hiddenOptions.push('scope_wh');
|
|
}
|
|
|
|
}else if( component.hasClass(config.systemClass) ){
|
|
// disable system menu entries
|
|
if(component.data('locked') === true){
|
|
hiddenOptions.push('delete_system');
|
|
}
|
|
|
|
// disable ingame options if not IGB browser
|
|
if(! CCP.isInGameBrowser() ){
|
|
hiddenOptions.push('ingame');
|
|
}
|
|
}
|
|
|
|
return hiddenOptions;
|
|
};
|
|
|
|
/**
|
|
* get active menu entry options for a context menu
|
|
* @param component
|
|
* @returns {Array}
|
|
*/
|
|
var getActiveContextMenuOptions = function(component){
|
|
|
|
var activeOptions = [];
|
|
|
|
if(component instanceof jsPlumb.Connection){
|
|
var scope = component.scope;
|
|
|
|
if(component.hasType('wh_eol') === true){
|
|
activeOptions.push('wh_eol');
|
|
}
|
|
|
|
if(component.hasType('frigate') === true){
|
|
activeOptions.push('frigate');
|
|
}
|
|
if(component.hasType('preserve_mass') === true){
|
|
activeOptions.push('preserve_mass');
|
|
}
|
|
if(component.hasType('wh_reduced') === true){
|
|
activeOptions.push('status_reduced');
|
|
}else if(component.hasType('wh_critical') === true){
|
|
activeOptions.push('status_critical');
|
|
}else{
|
|
// not reduced is default
|
|
activeOptions.push('status_fresh');
|
|
}
|
|
|
|
}else if( component.hasClass(config.mapClass) ){
|
|
|
|
// active map menu entries
|
|
if(component.data('filter_scope') === 'wh'){
|
|
activeOptions.push('filter_wh');
|
|
}
|
|
if(component.data('filter_scope') === 'stargate'){
|
|
activeOptions.push('filter_stargate');
|
|
}
|
|
if(component.data('filter_scope') === 'jumpbridge'){
|
|
activeOptions.push('filter_jumpbridge');
|
|
}
|
|
}else if( component.hasClass(config.systemClass) ){
|
|
// active system menu entries
|
|
if(component.data('locked') === true){
|
|
activeOptions.push('lock_system');
|
|
}
|
|
if(component.data('rally') === true){
|
|
activeOptions.push('set_rally');
|
|
}
|
|
}
|
|
|
|
return activeOptions;
|
|
};
|
|
|
|
/**
|
|
* set observer for a given connection
|
|
* @param map
|
|
* @param connection
|
|
*/
|
|
var setConnectionObserver = function(map, connection){
|
|
|
|
// get map container
|
|
var mapElement = $( map.getContainer() );
|
|
|
|
// if the connection already exists -> do not set it twice
|
|
connection.unbind('contextmenu').bind('contextmenu', function(component, e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
// trigger menu "open
|
|
|
|
// get invisible menu entries
|
|
var hideOptions = getHiddenContextMenuOptions(component);
|
|
var activeOptions = getActiveContextMenuOptions(component);
|
|
$(e.target).trigger('pf:openContextMenu', [e, component, hideOptions, activeOptions]);
|
|
|
|
return false;
|
|
});
|
|
|
|
/**
|
|
* init context menu for all connections
|
|
* must be triggered manually on demand
|
|
*/
|
|
$(connection.canvas).contextMenu({
|
|
menuSelector: "#" + config.connectionContextMenuId,
|
|
menuSelected: function (params){
|
|
|
|
var action = params.selectedMenu.attr('data-action');
|
|
var activeConnection = params.component;
|
|
var activeScope = activeConnection.scope;
|
|
var activeScopeName = Util.getScopeInfoForConnection( activeScope, 'label');
|
|
|
|
switch(action){
|
|
case 'delete_connection':
|
|
// delete a single connection
|
|
|
|
// confirm dialog
|
|
bootbox.confirm('Is this connection really gone?', function(result) {
|
|
if(result){
|
|
$().deleteConnections([activeConnection]);
|
|
}
|
|
});
|
|
break;
|
|
case 'frigate': // set as frigate hole
|
|
case 'preserve_mass': // set "preserve mass
|
|
case 'wh_eol': // set "end of life"
|
|
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
activeConnection.toggleType( action );
|
|
|
|
$(activeConnection).markAsChanged();
|
|
break;
|
|
case 'status_fresh':
|
|
case 'status_reduced':
|
|
case 'status_critical':
|
|
var newStatus = action.split('_')[1];
|
|
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
setConnectionWHStatus(activeConnection, 'wh_' + newStatus);
|
|
$(activeConnection).markAsChanged();
|
|
break;
|
|
case 'scope_wh':
|
|
case 'scope_stargate':
|
|
case 'scope_jumpbridge':
|
|
var newScope = action.split('_')[1];
|
|
var newScopeName = Util.getScopeInfoForConnection( newScope, 'label');
|
|
|
|
bootbox.confirm('Change scope from ' + activeScopeName + ' to ' + newScopeName + '?', function(result) {
|
|
if(result){
|
|
|
|
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
setConnectionScope(activeConnection, newScope);
|
|
|
|
Util.showNotify({title: 'Connection scope changed', text: 'New scope: ' + newScopeName, type: 'success'});
|
|
|
|
$(activeConnection).markAsChanged();
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* mark a system as active
|
|
* @param map
|
|
* @param system
|
|
*/
|
|
var markSystemActive = function(map, system){
|
|
|
|
// deactivate all systems in map
|
|
var mapContainer = $( map.getContainer() );
|
|
|
|
mapContainer.find('.' + config.systemClass).removeClass(config.systemActiveClass);
|
|
|
|
// set current system active
|
|
system.addClass(config.systemActiveClass);
|
|
};
|
|
|
|
/**
|
|
* get system data out of its object
|
|
* @param info
|
|
* @returns {*}
|
|
*/
|
|
$.fn.getSystemInfo = function(info){
|
|
|
|
var systemInfo = [];
|
|
|
|
for(var i = 0; i < info.length; i++){
|
|
switch(info[i]){
|
|
case 'alias':
|
|
// get current system alias
|
|
var systemHeadNameElement = $(this).find('.' + config.systemHeadNameClass);
|
|
var alias = '';
|
|
if( systemHeadNameElement.hasClass('editable') ){
|
|
// xEditable is initiated
|
|
alias = systemHeadNameElement.editable('getValue', true);
|
|
}
|
|
|
|
systemInfo.push(alias );
|
|
break;
|
|
default:
|
|
systemInfo.push('bad system query');
|
|
}
|
|
|
|
}
|
|
|
|
if(systemInfo.length === 1){
|
|
return systemInfo[0];
|
|
}else{
|
|
return systemInfo;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* open "new system" dialog and add the system to map
|
|
* optional the new system is connected to a "sourceSystem" (if available)
|
|
*
|
|
* @param map
|
|
* @param options
|
|
*/
|
|
var showNewSystemDialog = function(map, options){
|
|
|
|
var mapContainer = $(map.getContainer());
|
|
|
|
// format system status for form select ------------------------------------------------------------------------
|
|
var systemStatus = {};
|
|
$.each(Init.systemStatus, function(status, statusData){
|
|
systemStatus[statusData.id] = statusData.label;
|
|
});
|
|
|
|
// default system status -> first status entry
|
|
var tempKeys = [];
|
|
for(var k in Init.systemStatus){
|
|
if (Init.systemStatus.hasOwnProperty(k)){
|
|
tempKeys.push(k);
|
|
}
|
|
}
|
|
var defaultSystemStatus = Init.systemStatus[ tempKeys[0] ].id;
|
|
|
|
|
|
// get current map data -> disable systems that are already on it ----------------------------------------------
|
|
var mapData = mapContainer.getMapDataFromClient({forceData: true});
|
|
var mapSystems = mapData.data.systems;
|
|
var mapSystemIds = [];
|
|
for(var i = 0; i < mapSystems.length; i++ ){
|
|
mapSystemIds.push( mapSystems[i].systemId );
|
|
}
|
|
|
|
// dialog data -------------------------------------------------------------------------------------------------
|
|
var data = {
|
|
id: config.systemDialogId,
|
|
selectClass: config.systemDialogSelectClass
|
|
};
|
|
|
|
// set current position as "default" system to add -------------------------------------------------------------
|
|
var currentCharacterLog = Util.getCurrentCharacterLog();
|
|
|
|
if(
|
|
currentCharacterLog !== false &&
|
|
mapSystemIds.indexOf( currentCharacterLog.system.id ) === -1
|
|
){
|
|
// current system is NOT already on this map
|
|
// set current position as "default" system to add
|
|
data.currentSystem = currentCharacterLog.system;
|
|
}
|
|
|
|
|
|
requirejs(['text!templates/dialog/system.html', 'mustache'], function(template, Mustache) {
|
|
|
|
var content = Mustache.render(template, data);
|
|
|
|
// disable modal focus event -> otherwise select2 is not working! -> quick fix
|
|
$.fn.modal.Constructor.prototype.enforceFocus = function() {};
|
|
|
|
var systemDialog = bootbox.dialog({
|
|
title: 'Add new system',
|
|
message: content,
|
|
buttons: {
|
|
close: {
|
|
label: 'cancel',
|
|
className: 'btn-default'
|
|
},
|
|
success: {
|
|
label: '<i class="fa fa-fw fa-check"></i> save',
|
|
className: 'btn-success',
|
|
callback: function (e) {
|
|
// get form Values
|
|
var form = $('#' + config.systemDialogId).find('form');
|
|
|
|
var systemDialogData = $(form).getFormValues();
|
|
|
|
// validate form
|
|
form.validator('validate');
|
|
|
|
// check weather the form is valid
|
|
var formValid = form.isValidForm();
|
|
|
|
if(formValid === false){
|
|
// don't close dialog
|
|
return false;
|
|
}
|
|
|
|
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
// calculate new system position -----------------------------------------------
|
|
var newPosition = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
var sourceSystem = null;
|
|
|
|
// add new position
|
|
if(options.sourceSystem !== undefined){
|
|
|
|
sourceSystem = options.sourceSystem;
|
|
|
|
// get new position
|
|
newPosition = calculateNewSystemPosition(sourceSystem);
|
|
}else{
|
|
// check mouse cursor position (add system to map)
|
|
newPosition = {
|
|
x: options.position.x,
|
|
y: options.position.y
|
|
};
|
|
}
|
|
|
|
systemDialogData.position = newPosition;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
var requestData = {
|
|
systemData: systemDialogData,
|
|
mapData: {
|
|
id: mapContainer.data('id')
|
|
}
|
|
};
|
|
|
|
saveSystem(map, requestData, sourceSystem, function(){
|
|
bootbox.hideAll();
|
|
});
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// init dialog
|
|
systemDialog.on('shown.bs.modal', function(e) {
|
|
|
|
var modalContent = $('#' + config.systemDialogId);
|
|
|
|
// init system select live search - some delay until modal transition has finished
|
|
var selectElement = modalContent.find('.' + config.systemDialogSelectClass);
|
|
selectElement.delay(240).initSystemSelect({
|
|
key: 'systemId',
|
|
disabledOptions: mapSystemIds
|
|
});
|
|
});
|
|
|
|
// init system status select
|
|
var modalFields = $('.bootbox .modal-dialog').find('.pf-editable-system-status');
|
|
|
|
modalFields.editable({
|
|
mode: 'inline',
|
|
emptytext: 'unknown',
|
|
onblur: 'submit',
|
|
showbuttons: false,
|
|
source: systemStatus,
|
|
value: defaultSystemStatus,
|
|
inputclass: config.systemDialogSelectClass
|
|
});
|
|
});
|
|
};
|
|
|
|
/**
|
|
* save a new system and add it to the map
|
|
* @param map
|
|
* @param requestData
|
|
* @param sourceSystem
|
|
* @param callback
|
|
*/
|
|
var saveSystem = function(map, requestData, sourceSystem, callback){
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: Init.path.saveSystem,
|
|
data: requestData,
|
|
dataType: 'json',
|
|
context: {
|
|
map: map,
|
|
sourceSystem: sourceSystem
|
|
}
|
|
}).done(function(newSystemData){
|
|
|
|
// draw new system to map
|
|
drawSystem(this.map, newSystemData, this.sourceSystem);
|
|
|
|
Util.showNotify({title: 'New system', text: newSystemData.name, type: 'success'});
|
|
|
|
// re-init "magnetizer" with new added system
|
|
if(config.mapMagnetizer === true){
|
|
var mapContainer = this.map.getContainer();
|
|
$(mapContainer).initMagnetizer();
|
|
|
|
// re/arrange systems (prevent overlapping)
|
|
MagnetizerWrapper.executeAtCenter(this.map);
|
|
}
|
|
|
|
if(callback){
|
|
callback();
|
|
}
|
|
}).fail(function( jqXHR, status, error) {
|
|
var reason = status + ' ' + error;
|
|
Util.showNotify({title: jqXHR.status + ': saveSystem', text: reason, type: 'warning'});
|
|
$(document).setProgramStatus('problem');
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* calculate the x/y coordinates for a new system - relativ to a source system
|
|
* @param sourceSystem
|
|
* @returns {{x: *, y: *}}
|
|
*/
|
|
var calculateNewSystemPosition = function(sourceSystem){
|
|
|
|
// related system is available
|
|
var currentX = sourceSystem.css('left');
|
|
var currentY = sourceSystem.css('top');
|
|
|
|
// remove "px"
|
|
currentX = parseInt( currentX.substring(0, currentX.length - 2) );
|
|
currentY = parseInt( currentY.substring(0, currentY.length - 2) );
|
|
|
|
var newPosition = {
|
|
x: currentX + config.newSystemOffset.x,
|
|
y: currentY + config.newSystemOffset.y
|
|
};
|
|
|
|
return newPosition;
|
|
};
|
|
|
|
/**
|
|
* updates all systems on map with current user Data (all users on this map)
|
|
* update the Data of the user that is currently viewing the map (if available)
|
|
* @param userData
|
|
* @returns {boolean}
|
|
*/
|
|
$.fn.updateUserData = function(userData){
|
|
|
|
var returnStatus = true;
|
|
|
|
// get new map instance or load existing
|
|
var map = getMapInstance(userData.config.id);
|
|
|
|
var mapElement = map.getContainer();
|
|
|
|
// get map tracking toggle value
|
|
// if "false" -> new systems/connections will not automatically added
|
|
var mapTracking = $('#' + config.headMapTrackingId).is(':checked');
|
|
|
|
|
|
// container must exist! otherwise systems can not be updated
|
|
if(mapElement !== undefined){
|
|
|
|
mapElement = $(mapElement);
|
|
|
|
// get current character log data
|
|
var currentCharacterLog = Util.getCurrentCharacterLog();
|
|
|
|
// check if map is frozen
|
|
if(mapElement.data('frozen') === true){
|
|
return returnStatus;
|
|
}
|
|
|
|
// data for header update
|
|
var headerUpdateData = {
|
|
mapId: userData.config.id,
|
|
userCount: 0 // active user in a map
|
|
};
|
|
|
|
// check if current user was found on the map
|
|
var currentUserOnMap = false;
|
|
|
|
// get all systems
|
|
var systems = mapElement.find('.' + config.systemClass);
|
|
|
|
for(var i = 0; i < systems.length; i++){
|
|
// get user Data for System
|
|
|
|
var system = $( systems[i] );
|
|
|
|
var systemId = $(system).data('systemId');
|
|
|
|
var tempUserData = null;
|
|
|
|
// check if user is currently in "this" system
|
|
var currentUserIsHere = false;
|
|
|
|
var j = userData.data.systems.length;
|
|
|
|
// search backwards to avoid decrement the counter after splice()
|
|
while (j--) {
|
|
var systemData = userData.data.systems[j];
|
|
|
|
// check if any user is in this system
|
|
if (systemId === systemData.id) {
|
|
tempUserData = systemData;
|
|
|
|
// add "user count" to "total map user count"
|
|
headerUpdateData.userCount += tempUserData.user.length;
|
|
|
|
// remove system from "search" array -> speed up loop
|
|
userData.data.systems.splice(j, 1);
|
|
}
|
|
}
|
|
|
|
// the current user can only be in a single system -------------------------------------------------------
|
|
if( !currentUserOnMap){
|
|
|
|
if(
|
|
currentCharacterLog &&
|
|
currentCharacterLog.system &&
|
|
currentCharacterLog.system.id === systemId
|
|
){
|
|
currentUserIsHere = true;
|
|
currentUserOnMap = true;
|
|
|
|
// set current location data for header update
|
|
headerUpdateData.currentSystemId = $(system).data('id');
|
|
headerUpdateData.currentSystemName = currentCharacterLog.system.name;
|
|
|
|
// check connection exists between new and previous systems --------o------------------------------
|
|
// e.g. a loop
|
|
if(
|
|
activeSystemCache &&
|
|
mapTracking &&
|
|
activeSystemCache.data('systemId') !== currentCharacterLog.system.id
|
|
){
|
|
// maybe a loop detected (both systems already on map -> connection missing
|
|
var connections = checkForConnection(map, activeSystemCache, system );
|
|
|
|
if(connections.length === 0){
|
|
var connectionData = {
|
|
source: activeSystemCache.data('id') ,
|
|
target: system.data('id'),
|
|
type: ['wh_fresh'] // default type.
|
|
};
|
|
|
|
var connection = drawConnection(map, connectionData);
|
|
saveConnection(connection);
|
|
}
|
|
|
|
}
|
|
|
|
// cache current location
|
|
activeSystemCache = system;
|
|
}
|
|
}
|
|
|
|
system.updateSystemUserData(map, tempUserData, currentUserIsHere);
|
|
}
|
|
|
|
// current user was not found on any map system -> add new system to map where the user is in ----------------
|
|
// this is restricted to IGB-usage! CharacterLog data is always set through the IGB
|
|
// ->this prevent adding the same system multiple times, if a user is online with IGB AND OOG
|
|
if(
|
|
currentUserOnMap === false &&
|
|
currentCharacterLog &&
|
|
mapTracking
|
|
){
|
|
// add new system to the map
|
|
var requestData = {
|
|
systemData: {
|
|
systemId: currentCharacterLog.system.id
|
|
},
|
|
mapData: {
|
|
id: userData.config.id
|
|
}
|
|
};
|
|
|
|
// check if a system jump is detected previous system !== current system
|
|
// and add a connection to the previous system as well
|
|
// hint: if a user just logged on -> there is no active system cached
|
|
var sourceSystem = false;
|
|
if(
|
|
activeSystemCache &&
|
|
activeSystemCache.data('systemId') !== currentCharacterLog.system.id
|
|
){
|
|
|
|
// draw new connection
|
|
sourceSystem = activeSystemCache;
|
|
// calculate new system coordinates
|
|
requestData.systemData.position = calculateNewSystemPosition(sourceSystem);
|
|
}
|
|
|
|
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
|
|
|
saveSystem(map, requestData, sourceSystem, false);
|
|
}
|
|
|
|
// trigger document event -> update header
|
|
$(document).trigger('pf:updateHeaderMapData', headerUpdateData);
|
|
}
|
|
|
|
return returnStatus;
|
|
};
|
|
|
|
/**
|
|
* collect all map data for export/save for a map
|
|
* this function returns the "client" data NOT the "server" data for a map
|
|
* @param options
|
|
* @returns {*}
|
|
*/
|
|
$.fn.getMapDataFromClient = function(options){
|
|
|
|
var mapElement = $(this);
|
|
|
|
var map = getMapInstance( mapElement.data('id') );
|
|
|
|
var mapData = {};
|
|
|
|
// check if there is an active map counter that prevents collecting map data
|
|
var overlay = mapElement.getMapOverlay('timer');
|
|
var counterChart = overlay.getMapCounter();
|
|
|
|
var interval = counterChart.data('interval');
|
|
|
|
if(
|
|
! interval ||
|
|
options.forceData === true
|
|
){
|
|
|
|
// map config -----------------------------------------------------------
|
|
var mapConfig = {};
|
|
mapConfig.id = parseInt( mapElement.data('id') );
|
|
mapConfig.name = mapElement.data('name');
|
|
mapConfig.scope = {
|
|
id: parseInt( mapElement.data('scopeId') )
|
|
};
|
|
mapConfig.icon = mapElement.data('icon');
|
|
mapConfig.type = {
|
|
id: parseInt( mapElement.data('typeId') )
|
|
};
|
|
mapConfig.created = parseInt( mapElement.data('created') );
|
|
mapConfig.updated = parseInt( mapElement.data('updated') );
|
|
mapData.config = mapConfig;
|
|
|
|
// map data -------------------------------------------------------------
|
|
var data = {};
|
|
|
|
// systems data ---------------------------------------------------------
|
|
var systemsData = [];
|
|
var systems = mapElement.find('.' + config.systemClass);
|
|
|
|
for(var i = 0; i < systems.length; i++){
|
|
var tempSystem = $(systems[i]);
|
|
|
|
// check if system data should be added
|
|
var addSystemData = true;
|
|
if(
|
|
options.checkForChange === true &&
|
|
!tempSystem.hasChanged()
|
|
){
|
|
addSystemData = false;
|
|
}
|
|
|
|
if(addSystemData){
|
|
systemsData.push( tempSystem.getSystemData() );
|
|
}
|
|
}
|
|
|
|
data.systems = systemsData;
|
|
|
|
// connections ----------------------------------------------------------
|
|
var connections = map.getAllConnections();
|
|
var connectionsFormatted = [];
|
|
|
|
// new connections cache
|
|
var updatedConnectionCache = {};
|
|
|
|
// format connections
|
|
for(var j = 0; j < connections.length; j++){
|
|
var tempConnection = connections[j];
|
|
|
|
// check if connection data should be added
|
|
var addConnectionData = true;
|
|
if(
|
|
options.checkForChange === true &&
|
|
!$(tempConnection).hasChanged()
|
|
){
|
|
addConnectionData = false;
|
|
}
|
|
|
|
var connectionData = getDataByConnection(tempConnection);
|
|
|
|
if(addConnectionData){
|
|
connectionsFormatted.push( connectionData );
|
|
}
|
|
|
|
// add to cache
|
|
updatedConnectionCache[connectionData.id] = tempConnection;
|
|
}
|
|
|
|
// overwrite connection cache
|
|
connectionCache[mapConfig.id] = updatedConnectionCache;
|
|
|
|
data.connections = connectionsFormatted;
|
|
|
|
mapData.data = data;
|
|
}else{
|
|
return false;
|
|
}
|
|
|
|
return mapData;
|
|
};
|
|
|
|
/**
|
|
* get all relevant data for a system object
|
|
* @returns {{}}
|
|
*/
|
|
$.fn.getSystemData = function(){
|
|
var system = $(this);
|
|
|
|
var systemData = {};
|
|
systemData.id = parseInt( system.data('id') );
|
|
systemData.systemId = parseInt( system.data('systemId') );
|
|
systemData.name = system.data('name');
|
|
systemData.alias = system.getSystemInfo(['alias']);
|
|
systemData.effect = system.data('effect');
|
|
systemData.type = {
|
|
id: system.data('typeId')
|
|
};
|
|
systemData.security = system.data('security');
|
|
systemData.trueSec = system.data('trueSec');
|
|
systemData.region = {
|
|
id: system.data('regionId'),
|
|
name: system.data('region')
|
|
};
|
|
systemData.constellation = {
|
|
id: system.data('constellationId'),
|
|
name: system.data('constellation')
|
|
};
|
|
systemData.status = {
|
|
id: system.data('statusId')
|
|
};
|
|
systemData.locked = system.data('locked') ? 1 : 0;
|
|
systemData.rally = system.data('rally') ? 1 : 0;
|
|
systemData.currentUser = system.data('currentUser'); // if user is currently in this system
|
|
systemData.statics = system.data('statics');
|
|
systemData.updated = {
|
|
updated: parseInt( system.data('updated') )
|
|
};
|
|
systemData.userCount = (system.data('userCount') ? parseInt( system.data('userCount') ) : 0);
|
|
|
|
// position -----------------------------------------------------------------
|
|
var positionData = {};
|
|
var currentX = system.css('left');
|
|
var currentY = system.css('top');
|
|
|
|
// remove 'px'
|
|
positionData.x = parseInt( currentX.substring(0, currentX.length - 2) );
|
|
positionData.y = parseInt( currentY.substring(0, currentY.length - 2) );
|
|
|
|
systemData.position = positionData;
|
|
|
|
return systemData;
|
|
};
|
|
|
|
/**
|
|
* get all relevant data for a connection object
|
|
* @param connection
|
|
* @returns {{id: Number, source: Number, sourceName: (*|T|JQuery|{}), target: Number, targetName: (*|T|JQuery), scope: *, type: *, updated: Number}}
|
|
*/
|
|
var getDataByConnection = function(connection){
|
|
|
|
var source = $(connection.source);
|
|
var target = $(connection.target);
|
|
|
|
var id = connection.getParameter('connectionId');
|
|
var updated = connection.getParameter('updated');
|
|
|
|
var connectionTypes = connection.getType();
|
|
|
|
// normalize connection array
|
|
connectionTypes = $.grep(connectionTypes, function(n){
|
|
if(
|
|
n.length > 0 &&
|
|
n !== 'default' // this is added by jsplumb by default -_-
|
|
){
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
});
|
|
|
|
var data = {
|
|
id: id ? id : 0,
|
|
source: parseInt( source.data('id') ),
|
|
sourceName: source.data('name'),
|
|
target: parseInt( target.data('id') ),
|
|
targetName: target.data('name'),
|
|
scope: connection.scope,
|
|
type: connectionTypes,
|
|
updated: updated ? updated : 0
|
|
};
|
|
|
|
return data;
|
|
};
|
|
|
|
/**
|
|
* removes a map instance from local cache
|
|
* @param mapId
|
|
*/
|
|
var clearMapInstance = function(mapId){
|
|
if(typeof activeInstances[mapId] === 'object'){
|
|
delete activeInstances[mapId];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* get a new jsPlumb map instance or or get a cached one for update
|
|
* @param mapId
|
|
* @returns {*}
|
|
*/
|
|
var getMapInstance = function(mapId){
|
|
|
|
if(typeof activeInstances[mapId] !== 'object'){
|
|
// create new instance
|
|
jsPlumb.Defaults.LogEnabled = true;
|
|
|
|
var newJsPlumbInstance = jsPlumb.getInstance({
|
|
Anchor: 'Continuous', // anchors on each site
|
|
Container: null, // will be set as soon as container is connected to DOM
|
|
PaintStyle: {
|
|
lineWidth: 4, // width of a Connector's line. An integer.
|
|
strokeStyle: 'red', // color for a Connector
|
|
outlineColor: 'red', // color of the outline for an Endpoint or Connector. see fillStyle examples.
|
|
outlineWidth: 2 // width of the outline for an Endpoint or Connector. An integer.
|
|
},
|
|
Connector: [ 'Bezier', { curviness: 40 } ], // default connector style (this is not used!) all connections have their own style (by scope)
|
|
Endpoint: [ 'Dot', { radius: 5 } ],
|
|
ReattachConnections: false, // re-attach connection if dragged with mouse to "nowhere"
|
|
Scope: Init.defaultMapScope, // default map scope for connections
|
|
LogEnabled: true
|
|
});
|
|
|
|
// register all available connection types ------------------------------
|
|
newJsPlumbInstance.registerConnectionTypes(globalMapConfig.connectionTypes);
|
|
|
|
// event after a new connection is established --------------------------
|
|
newJsPlumbInstance.bind('connection', function(info, e) {
|
|
// set connection observer
|
|
setConnectionObserver(newJsPlumbInstance, info.connection);
|
|
});
|
|
|
|
// event after connection moved -----------------------------------------
|
|
newJsPlumbInstance.bind('connectionMoved', function(info, e) {
|
|
|
|
});
|
|
|
|
// event after DragStop a connection or new connection ------------------
|
|
newJsPlumbInstance.bind('beforeDrop', function(info) {
|
|
var connection = info.connection;
|
|
|
|
// lock the target system for "click" events
|
|
// to prevent loading system information
|
|
var sourceSystem = $('#' + info.sourceId);
|
|
var targetSystem = $('#' + info.targetId);
|
|
sourceSystem.addClass('no-click');
|
|
targetSystem.addClass('no-click');
|
|
setTimeout(function(){
|
|
sourceSystem.removeClass('no-click');
|
|
targetSystem.removeClass('no-click');
|
|
}, Init.timer.DBL_CLICK + 50);
|
|
|
|
// set "default" connection status only for NEW connections
|
|
if(!connection.suspendedElement){
|
|
setConnectionWHStatus(connection, getDefaultConnectionTypeByScope(connection.scope) );
|
|
}
|
|
|
|
// prevent multiple connections between same systems
|
|
var connections = checkForConnection(newJsPlumbInstance, info.sourceId, info.targetId );
|
|
|
|
if(connections.length > 1){
|
|
bootbox.confirm('Connection already exists. Do you really want to add an additional one?', function(result) {
|
|
if(!result){
|
|
connection._jsPlumb.instance.detach(connection);
|
|
}
|
|
});
|
|
}
|
|
|
|
// always save the new connection
|
|
saveConnection(connection);
|
|
|
|
return true;
|
|
});
|
|
|
|
// event before Detach connection ---------------------------------------
|
|
newJsPlumbInstance.bind('beforeDetach', function(info) {
|
|
return true;
|
|
});
|
|
|
|
newJsPlumbInstance.bind('connectionDetached', function(info, e){
|
|
// a connection is manually (drag&drop) detached! otherwise this event should not be send!
|
|
var connection = info.connection;
|
|
$().deleteConnections([connection]);
|
|
});
|
|
|
|
newJsPlumbInstance.bind('checkDropAllowed', function(params){
|
|
// connections can not be attached to foreign endpoints
|
|
// the only endpoint available is endpoint from where the connection was dragged away (re-attach)
|
|
|
|
return true;
|
|
});
|
|
|
|
activeInstances[mapId] = newJsPlumbInstance;
|
|
}
|
|
|
|
return activeInstances[mapId];
|
|
};
|
|
|
|
/**
|
|
* load OR updates system map
|
|
* @param mapConfig
|
|
*/
|
|
$.fn.loadMap = function(mapConfig, options){
|
|
|
|
// parent element where the map will be loaded
|
|
var parentElement = $(this);
|
|
|
|
// add context menus to dom (if not already
|
|
initMapContextMenu();
|
|
initConnectionContextMenu();
|
|
initSystemContextMenu();
|
|
|
|
// new map init
|
|
var newMap = false;
|
|
|
|
// init jsPlumb
|
|
jsPlumb.ready(function() {
|
|
// get new map instance or load existing
|
|
mapConfig.map = getMapInstance(mapConfig.config.id);
|
|
|
|
// check for map Container -> first time initialization
|
|
if(mapConfig.map.getContainer() === undefined){
|
|
// new map instance
|
|
newMap = true;
|
|
}
|
|
|
|
// draw/update map initial map and set container
|
|
var mapContainer = updateMap(parentElement, mapConfig);
|
|
|
|
if(newMap){
|
|
// init custom scrollbars and add overlay
|
|
parentElement.initMapScrollbar();
|
|
}
|
|
|
|
// callback function after tab switch
|
|
function switchTabCallback( mapName, mapContainer ){
|
|
Util.showNotify({title: 'Map initialized', text: mapName + ' - loaded', type: 'success'});
|
|
|
|
if( config.mapMagnetizer === true ){
|
|
mapContainer.initMagnetizer();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if(options.showAnimation){
|
|
// show nice visualization effect
|
|
mapContainer.visualizeMap('show', function(){
|
|
switchTabCallback( mapConfig.config.name, mapContainer );
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* init scrollbar for Map element
|
|
*/
|
|
$.fn.initMapScrollbar = function(){
|
|
// get Map Scrollbar
|
|
var scrollableElement = $(this).find('.' + config.mapWrapperClass);
|
|
initCustomScrollbar( scrollableElement );
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// add map overlays after scrollbar is initialized
|
|
// because of its absolute position
|
|
scrollableElement.initMapOverlays();
|
|
};
|
|
|
|
/**
|
|
* init a custom scrollbar
|
|
* @param scrollableElement
|
|
*/
|
|
var initCustomScrollbar = function( scrollableElement ){
|
|
|
|
// prevent multiple initialization
|
|
$(scrollableElement).mCustomScrollbar('destroy');
|
|
|
|
// init custom scrollbars
|
|
$(scrollableElement).mCustomScrollbar({
|
|
axis: 'x',
|
|
theme: 'light-thick',
|
|
scrollInertia: 300,
|
|
autoExpandScrollbar: false,
|
|
scrollButtons:{
|
|
scrollAmount: 30,
|
|
enable: true
|
|
},
|
|
callbacks:{
|
|
onTotalScrollOffset: 0,
|
|
onTotalScrollBackOffset: 0,
|
|
alwaysTriggerOffsets:true,
|
|
onScrollStart: function(){
|
|
// hide all open xEditable fields
|
|
$(this).find('.editable').editable('hide');
|
|
|
|
// hide all system head tooltips
|
|
$(this).find('.' + config.systemHeadClass + ' .fa').tooltip('hide');
|
|
},
|
|
whileScrolling:function(){
|
|
// update scroll position for drag-frame-selection
|
|
var mapElement = $(scrollableElement).find('.' + config.mapClass);
|
|
$(mapElement).data('scrollLeft', this.mcs.left);
|
|
$(mapElement).data('scrollTop', this.mcs.top);
|
|
}
|
|
},
|
|
|
|
advanced: {
|
|
updateOnBrowserResize: true,
|
|
updateOnContentResize: true,
|
|
autoExpandHorizontalScroll: true,
|
|
autoScrollOnFocus: "div"
|
|
},
|
|
mouseWheel:{
|
|
enable: false, // scroll weel currently disabled
|
|
scrollAmount: 'auto',
|
|
axis: 'x',
|
|
preventDefault: true
|
|
},
|
|
scrollbarPosition: 'inside',
|
|
autoDraggerLength: true
|
|
//autoHideScrollbar: false
|
|
});
|
|
};
|
|
|
|
/**
|
|
* scroll to a specific position in the map
|
|
* @returns {*} // string or id
|
|
*/
|
|
$.fn.scrollTo = function(position){
|
|
return this.each(function(){
|
|
$(this).mCustomScrollbar('scrollTo', position);
|
|
});
|
|
};
|
|
|
|
return {
|
|
clearMapInstance: clearMapInstance
|
|
};
|
|
|
|
}); |