Files
pathfinder/js/app/map/contextmenu.js
Mark Friedrich 1de67f8dbf - New "station" data added, closed #858
- Improved system deeplinks. EveEye.com added, closed #859
- Improved cronjob performance for "SovereigntyData" import, closed #853
- Updated static DB dump for `eve_universe.sql`
2019-09-30 19:36:39 +02:00

304 lines
11 KiB
JavaScript

/**
* context menu
*/
define([
'jquery',
'app/render'
], ($, Render) => {
'use strict';
let config = {
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
endpointContextMenuId: 'pf-map-endpoint-contextmenu', // id for "endpoints" context menu
systemContextMenuId: 'pf-map-system-contextmenu', // id for "systems" context menu
animationInType: 'transition.flipXIn',
animationInDuration: 150,
animationOutType: 'transition.flipXOut',
animationOutDuration: 150
};
/**
* calc menu X coordinate
* @param e
* @param menuWidth
* @returns {number|*}
*/
let getMenuLeftCoordinate = (e, menuWidth) => {
let mouseWidth = e.pageX;
let pageWidth = $(window).width();
// opening menu would pass the side of the page
if(mouseWidth + menuWidth > pageWidth &&
menuWidth < mouseWidth){
return mouseWidth - menuWidth;
}
return mouseWidth;
};
/**
* calc menu Y coordinate
* @param e
* @param menuHeight
* @returns {number|*}
*/
let getMenuTopCoordinate = (e, menuHeight) => {
let mouseHeight = e.pageY;
let pageHeight = $(window).height();
// opening menu would pass the bottom of the page
if(mouseHeight + menuHeight > pageHeight &&
menuHeight < mouseHeight){
return mouseHeight - menuHeight;
}
return mouseHeight;
};
/**
* render context menu template for maps
* @returns {*}
*/
let renderMapContextMenu = () => {
let moduleData = {
id: config.mapContextMenuId,
items: [
{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'},
{subIcon: '', subAction: 'filter_abyssal', subText: 'abyssal'}
]},
{icon: 'fa-sitemap', action: 'map', text: 'map', subitems: [
{subIcon: 'fa-edit', subAction: 'map_edit', subText: 'edit map'},
{subIcon: 'fa-street-view', subAction: 'map_info', subText: 'map info'},
]},
{divider: true, action: 'delete_systems'},
{icon: 'fa-trash', action: 'delete_systems', text: 'delete systems'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* render context menu template for connections
* @returns {*}
*/
let renderConnectionContextMenu = () => {
let moduleData = {
id: config.connectionContextMenuId,
items: [
{icon: 'fa-hourglass-end', action: 'wh_eol', text: 'toggle EOL'},
{icon: 'fa-exclamation-triangle', action: 'preserve_mass', text: 'preserve mass'},
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'mass status', subitems: [
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-gray', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-orange', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-redDarker', subAction: 'status_critical', subText: 'stage 3 (critical)'}
]},
{icon: 'fa-reply fa-rotate-180', action: 'wh_jump_mass_change', text: 'ship size', subitems: [
{subIcon: 'fa-char', subChar: 'S', subAction: 'wh_jump_mass_s', subText: 'smallest ships'},
{subIcon: 'fa-char', subChar: 'M', subAction: 'wh_jump_mass_m', subText: 'medium ships'},
{subIcon: 'fa-char', subChar: 'L', subAction: 'wh_jump_mass_l', subText: 'larger ships'},
{subIcon: 'fa-char', subChar: 'XL', subAction: 'wh_jump_mass_xl', subText: 'capital ships'}
]},
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
]},
{divider: true, action: 'separator'} ,
{icon: 'fa-unlink', action: 'delete_connection', text: 'detach'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* render context menu template for endpoints
* @returns {*}
*/
let renderEndpointContextMenu = () => {
let moduleData = {
id: config.endpointContextMenuId,
items: [
{icon: 'fa-globe', action: 'bubble', text: 'bubbled'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* render context menu template for systems
* @param systemStatusData
* @returns {*}
*/
let renderSystemContextMenu = systemStatusData => {
let statusData = [];
for(let [statusName, data] of Object.entries(systemStatusData)){
statusData.push({
subIcon: 'fa-tag',
subIconClass: data.class,
subAction: 'change_status_' + statusName,
subText: data.label
});
}
let 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-volume-up', action: 'set_rally', text: 'set rally point'},
{icon: 'fa-tags', text: 'set status', subitems: statusData},
{icon: 'fa-route', action: 'find_route', text: 'find route'},
{icon: 'fa-object-group', action: 'select_connections', text: 'select connections'},
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
{subIcon: 'fa-flag', 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: 'delete_system'},
{icon: 'fa-trash', action: 'delete_system', text: 'delete system(s)'}
]
};
return Render.render('modules/contextmenu', moduleData);
};
/**
* prepare (hide/activate/disable) some menu options
* @param menuElement
* @param hiddenOptions
* @param activeOptions
* @param disabledOptions
* @returns {*}
*/
let prepareMenu = (menuElement, hiddenOptions, activeOptions, disabledOptions) => {
let menuLiElements = menuElement.find('li');
// reset all menu entries
menuLiElements.removeClass('active').removeClass('disabled').show();
// hide specific menu entries
for(let action of hiddenOptions){
menuElement.find('li[data-action="' + action + '"]').hide();
}
//set active specific menu entries
for(let action of activeOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('active');
}
//disable specific menu entries
for(let action of disabledOptions){
menuElement.find('li[data-action="' + action + '"]').addClass('disabled');
}
return menuElement;
};
/**
* close all context menus (map, connection,...)
* @param excludeMenu
*/
let closeMenus = excludeMenu => {
let allMenus = $('.dropdown-menu[role="menu"]');
if(excludeMenu){
allMenus = allMenus.not(excludeMenu);
}
allMenus.velocity(config.animationOutType, {
duration: config.animationOutDuration
});
};
/**
* open menu handler
* @param menuConfig
* @param e
* @param context
*/
let openMenu = (menuConfig, e, context) => {
let menuElement = $('#' + menuConfig.id);
// close all other context menus
closeMenus(menuElement);
// remove menu list click event
// -> required in case the close handler could not remove them properly
// -> this happens if menu re-opens without closing (2x right click)
menuElement.off('click.contextMenuSelect', 'li');
// hide/activate/disable
menuElement = prepareMenu(menuElement, menuConfig.hidden, menuConfig.active, menuConfig.disabled);
menuElement.css({
position: 'absolute',
left: getMenuLeftCoordinate(e, menuElement.width()),
top: getMenuTopCoordinate(e, menuElement.height())
}).velocity(config.animationInType, {
duration: config.animationInDuration,
complete: function(){
context = {
original: {
event: e,
context: context,
},
selectCallback: menuConfig.selectCallback
};
$(this).one('click.contextMenuSelect', 'li', context, selectHandler);
}
});
};
/**
* menu item select handler
* @param e
*/
let selectHandler = e => {
if(e.data.selectCallback){
e.data.selectCallback(
$(e.currentTarget).attr('data-action'),
e.data.original.context.component,
e.data.original.event
);
}
};
/**
* default config (skeleton) for valid context menu configuration
* @returns {{hidden: Array, active: Array, disabled: Array, id: string, selectCallback: null}}
*/
let defaultMenuOptionConfig = () => {
return {
'id': '',
'selectCallback': null,
'hidden': [],
'active': [],
'disabled': []
};
};
return {
config: config,
defaultMenuOptionConfig: defaultMenuOptionConfig,
renderMapContextMenu: renderMapContextMenu,
renderConnectionContextMenu: renderConnectionContextMenu,
renderEndpointContextMenu: renderEndpointContextMenu,
renderSystemContextMenu: renderSystemContextMenu,
openMenu: openMenu,
closeMenus: closeMenus
};
});