- JS for WebWorker extension, #420

- improved route calculation, closed #311
- improved signature updates/sync
- improved "online status" monitoring
- improved "task manager"
- improved map sync
- updated "Velocity" library 1.2.3 -> 1.4.1
- updated "Velocity UI" library 5.0.4 -> 5.2.0
This commit is contained in:
Exodus4D
2017-01-06 16:45:21 +01:00
parent 8fab4d5845
commit 72a968199a
41 changed files with 7675 additions and 6266 deletions

22
composer.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "exodus4d/pathfinder",
"description": "Mapping tool for EVE ONLINE",
"minimum-stability": "stable",
"license": "MIT",
"authors": [
{
"name": "Mark Friedrich",
"email": "pathfinder@exodus4d.de"
}
],
"autoload": {
"psr-4": {
"Exodus4D\\Pathfinder\\": "app/main"
}
},
"require": {
"php-64bit": ">=7.0",
"ext-zmq": "1.1.*",
"react/zmq": "0.3.*"
}
}

View File

@@ -26,8 +26,8 @@ requirejs.config({
text: 'lib/requirejs/text', // v2.0.12 A RequireJS/AMD loader plugin for loading text resources.
mustache: 'lib/mustache.min', // v1.0.0 Javascript template engine - http://mustache.github.io
localForage: 'lib/localforage.min', // v1.4.2 localStorage library - https://mozilla.github.io/localForage
velocity: 'lib/velocity.min', // v1.2.2 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.0.4 plugin for velocity - http://julian.com/research/velocity/#uiPack
velocity: 'lib/velocity.min', // v1.4.1 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin http://plugins.adchsm.me/slidebars
jsPlumb: 'lib/dom.jsPlumb-1.7.6', // v1.7.6 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey

View File

@@ -5,7 +5,7 @@ define([
], function($, Init, Util) {
'use strict';
var config = {
let config = {
counterDigitSmallClass: 'pf-digit-counter-small',
counterDigitLargeClass: 'pf-digit-counter-large'
};
@@ -15,13 +15,13 @@ define([
* @param element
* @param tempDate
*/
var updateDateDiff = function(element, tempDate){
var diff = Util.getTimeDiffParts(tempDate, new Date());
var days = diff.days;
var hrs = diff.hours;
var min = diff.min;
var leftSec = diff.sec;
var value = [];
let updateDateDiff = function(element, tempDate){
let diff = Util.getTimeDiffParts(tempDate, new Date());
let days = diff.days;
let hrs = diff.hours;
let min = diff.min;
let leftSec = diff.sec;
let value = [];
if(
days > 0 ||
@@ -58,19 +58,22 @@ define([
*/
$.fn.initTimestampCounter = function(){
return this.each(function(){
var element = $(this);
var timestamp = parseInt( element.text() );
let element = $(this);
let timestamp = parseInt( element.text() );
// do not init twice
if(timestamp > 0){
// mark as init
element.attr('data-counter', 'init');
var date = new Date( timestamp * 1000);
let date = new Date( timestamp * 1000);
updateDateDiff(element, date);
var refreshIntervalId = window.setInterval(function(){
// show element (if invisible) after first update
element.css({'visibility': 'initial'});
let refreshIntervalId = window.setInterval(function(){
// update element with current time
if( !element.hasClass('stopCounter')){

View File

@@ -6,7 +6,7 @@ define(['jquery'], function($) {
'use strict';
var Config = {
let Config = {
path: {
img: 'public/img/', // path for images
// user API
@@ -22,6 +22,7 @@ define(['jquery'], function($) {
searchAccess: 'api/access/search', // ajax URL - search user/corporation/ally by name
// main config/map ping API
initMap: 'api/map/init', // ajax URL - get static data
getAccessData: 'api/map/getAccessData', // ajax URL - get map access tokens (WebSocket)
updateMapData: 'api/map/updateData', // ajax URL - main map update trigger
updateUserData: 'api/map/updateUserData', // ajax URL - main map user data trigger
// map API
@@ -63,11 +64,35 @@ define(['jquery'], function($) {
splashOverlay: 300, // "splash" loading overlay
headerLink: 100, // links in head bar
mapOverlay: 200, // show/hide duration for map overlays
mapMoveSystem: 300, // system position has changed animation
mapMoveSystem: 180, // system position has changed animation
mapDeleteSystem: 200, // remove system from map
mapModule: 200, // show/hide of an map module
dialogEvents: 180 // dialog events /slide/show/...
},
syncStatus: {
type: 'ajax',
webSocket: {
status: 'closed',
class: 'txt-color-danger',
timestamp: undefined
},
sharedWorker: {
status: 'offline', // SharedWorker status
class: 'txt-color-danger',
timestamp: undefined
},
ajax: {
status: 'enabled',
class: 'txt-color-success',
timestamp: undefined
}
},
performanceLogging: {
keyServerMapData: 'UPDATE_SERVER_MAP', // ajax request update map data
keyClientMapData: 'UPDATE_CLIENT_MAP', // update client map data
keyServerUserData: 'UPDATE_SERVER_USER_DATA', // ajax request update map user data
keyClientUserData: 'UPDATE_CLIENT_USER_DATA', // update client map user data
},
mapIcons: [ // map tab-icons
{
class: 'fa-desktop',

View File

@@ -11,288 +11,312 @@ define([
'use strict';
var logData = []; // cache object for all log entries
var logDataTable = null; // "Datatables" Object
let logData = []; // cache object for all log entries
let logDataTable = null; // "Datatables" Object
// Morris charts data
var maxGraphDataCount = 30; // max date entries for a graph
var chartData = {}; // chart Data object for all Morris Log graphs
let maxGraphDataCount = 30; // max date entries for a graph
let chartData = {}; // chart Data object for all Morris Log graphs
var config = {
dialogDynamicAreaClass: 'pf-dynamic-area', // class for dynamic areas
logGraphClass: 'pf-log-graph', // class for all log Morris graphs
tableToolsClass: 'pf-table-tools' // class for table tools
let config = {
taskDialogId: 'pf-task-dialog', // id for map "task manager" dialog
dialogDynamicAreaClass: 'pf-dynamic-area', // class for dynamic areas
timestampCounterClass: 'pf-timestamp-counter', // class for "timestamp" counter
taskDialogStatusAreaClass: 'pf-task-dialog-status', // class for "status" dynamic area
taskDialogLogTableAreaClass: 'pf-task-dialog-table', // class for "log table" dynamic area
logGraphClass: 'pf-log-graph', // class for all log Morris graphs
tableToolsClass: 'pf-table-tools' // class for table tools
};
/**
* get log time string
* @returns {string}
*/
var getLogTime = function(){
var serverTime = Util.getServerTime();
var logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
let getLogTime = function(){
let serverTime = Util.getServerTime();
let logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
return logTime;
};
/**
* updated "sync status" dynamic dialog area
*/
let updateSyncStatus = function(){
// check if task manager dialog is open
let logDialog = $('#' + config.taskDialogId);
if(logDialog.length){
// dialog is open
requirejs(['text!templates/modules/sync_status.html', 'mustache'], function(templateSyncStatus, Mustache) {
let data = {
timestampCounterClass: config.timestampCounterClass,
syncStatus: Init.syncStatus,
isWebSocket: () => {
return (Util.getSyncType() === 'webSocket');
},
isAjax: () => {
return (Util.getSyncType() === 'ajax');
}
};
let syncStatusElement = $( Mustache.render(templateSyncStatus, data ) );
logDialog.find('.' + config.taskDialogStatusAreaClass).html( syncStatusElement );
logDialog.find('.' + config.timestampCounterClass).initTimestampCounter();
syncStatusElement.initTooltips({
placement: 'right'
});
});
}
};
/**
* shows the logging dialog
*/
var showDialog = function(){
let showDialog = function(){
// dialog content
var content = $('<div>');
// content row for log graphs
var rowElementGraphs = $('<div>', {
class: 'row'
});
content.append(rowElementGraphs);
var tableHeadline = $('<h4>', {
text: ' Processes'
}).prepend( $('<i>', {
class: ['fa', 'fa-fw', 'fa-lg', 'fa-microchip'].join(' ')
}));
// add content Structure to dome before table initialization
content.append(tableHeadline);
// log table area --------------------------------------------------
var logTableArea = $('<div>', {
class: config.dialogDynamicAreaClass
});
var logTableActionBar = $('<div>', {
class: config.tableToolsClass
});
logTableArea.append(logTableActionBar);
var logTable = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
});
logTableArea.append(logTable);
content.append(logTableArea);
// init log table
logDataTable = logTable.DataTable({
paging: true,
ordering: true,
order: [ 1, 'desc' ],
autoWidth: false,
hover: false,
pageLength: 15,
lengthMenu: [[10, 15, 25, 50, 50], [10, 15, 25, 50, 50]],
data: logData, // load cached logs (if available)
language: {
emptyTable: 'No entries',
zeroRecords: 'No entries found',
lengthMenu: 'Show _MENU_ entries',
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
},
columnDefs: [
{
targets: 0,
title: '<i class="fa fa-lg fa-tag"></i>',
width: '18px',
searchable: false,
class: ['text-center'].join(' '),
data: 'status'
},{
targets: 1,
title: '<i class="fa fa-lg fa-fw fa-clock-o"></i>&nbsp;&nbsp;',
width: '50px',
searchable: true,
class: 'text-right',
data: 'time'
},{
targets: 2,
title: '<i class="fa fa-lg fa-fw fa-history"></i>&nbsp;&nbsp;',
width: '35px',
searchable: false,
class: 'text-right',
sType: 'html',
data: 'duration'
},{
targets: 3,
title: 'description',
searchable: true,
data: 'description'
},{
targets: 4,
title: 'type',
width: '40px',
searchable: true,
class: ['text-center'].join(' '),
data: 'type'
},{
targets: 5,
title: 'Prozess-ID&nbsp;&nbsp;&nbsp;',
width: '80px',
searchable: false,
class: 'text-right',
data: 'key'
}
]
});
// open dialog
var logDialog = bootbox.dialog({
title: 'Task-Manager',
message: content,
size: 'large',
buttons: {
close: {
label: 'close',
className: 'btn-default'
}
}
});
// modal dialog is shown
logDialog.on('shown.bs.modal', function(e) {
// show Morris graphs ----------------------------------------------------------
// function for chart label formation
var labelYFormat = function(y){
return Math.round(y) + 'ms';
requirejs(['text!templates/dialog/task_manager.html', 'mustache'], function(templateTaskManagerDialog, Mustache) {
let data = {
id: config.taskDialogId,
dialogDynamicAreaClass: config.dialogDynamicAreaClass,
taskDialogStatusAreaClass: config.taskDialogStatusAreaClass,
taskDialogLogTableAreaClass: config.taskDialogLogTableAreaClass,
tableActionBarClass: config.tableToolsClass
};
for(var key in chartData) {
if(chartData.hasOwnProperty(key)) {
// create a chart for each key
let contentTaskManager = $( Mustache.render(templateTaskManagerDialog, data) );
var colElementGraph = $('<div>', {
class: ['col-md-6'].join(' ')
});
let rowElementGraphs = contentTaskManager.find('.row');
let taskDialogLogTableAreaElement = contentTaskManager.find('.' + config.taskDialogLogTableAreaClass);
let logTable = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
});
// graph element
var graphElement = $('<div>', {
class: config.logGraphClass
});
taskDialogLogTableAreaElement.append(logTable);
var graphArea = $('<div>', {
class: config.dialogDynamicAreaClass
}).append( graphElement );
// headline
var headline = $('<h4>', {
text: key
}).prepend(
$('<span>', {
class: ['txt-color', 'txt-color-grayLight'].join(' '),
text: 'Prozess-ID: '
})
);
// show update ping between function calls
var updateElement = $('<small>', {
class: ['txt-color', 'txt-color-blue', 'pull-right'].join(' ')
});
headline.append(updateElement).append('<br>');
// show average execution time
var averageElement = $('<small>', {
class: 'pull-right'
});
headline.append(averageElement);
colElementGraph.append( headline );
colElementGraph.append( graphArea );
graphArea.showLoadingAnimation();
rowElementGraphs.append( colElementGraph );
// cache DOM Elements that will be updated frequently
chartData[key].averageElement = averageElement;
chartData[key].updateElement = updateElement;
chartData[key].graph = Morris.Area({
element: graphElement,
data: [],
xkey: 'x',
ykeys: ['y'],
labels: [key],
units: 'ms',
parseTime: false,
ymin: 0,
yLabelFormat: labelYFormat,
padding: 10,
hideHover: true,
pointSize: 3,
lineColors: ['#375959'],
pointFillColors: ['#477372'],
pointStrokeColors: ['#313335'],
lineWidth: 2,
grid: false,
gridStrokeWidth: 0.3,
gridTextSize: 9,
gridTextFamily: 'Oxygen Bold',
gridTextColor: '#63676a',
behaveLikeLine: true,
goals: [],
goalLineColors: ['#66c84f'],
smooth: false,
fillOpacity: 0.3,
resize: true
});
graphArea.hideLoadingAnimation();
}
}
// ------------------------------------------------------------------------------
// add dataTable buttons (extension)
var buttons = new $.fn.dataTable.Buttons( logDataTable, {
buttons: [
// init log table
logDataTable = logTable.DataTable({
paging: true,
ordering: true,
order: [ 1, 'desc' ],
autoWidth: false,
hover: false,
pageLength: 10,
lengthMenu: [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, 'All']],
data: logData, // load cached logs (if available)
language: {
emptyTable: 'No entries',
zeroRecords: 'No entries found',
lengthMenu: 'Show _MENU_ entries',
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
},
columnDefs: [
{
extend: 'copy',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-clipboard"></i> copy'
targets: 0,
title: '<i class="fa fa-lg fa-tag"></i>',
width: '18px',
searchable: false,
class: ['text-center'].join(' '),
data: 'status'
},{
extend: 'csv',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-download"></i> csv'
targets: 1,
title: '<i class="fa fa-lg fa-fw fa-clock-o"></i>&nbsp;&nbsp;',
width: '50px',
searchable: true,
class: 'text-right',
data: 'time'
},{
targets: 2,
title: '<i class="fa fa-lg fa-fw fa-history"></i>&nbsp;&nbsp;',
width: '35px',
searchable: false,
class: 'text-right',
sType: 'html',
data: 'duration'
},{
targets: 3,
title: 'description',
searchable: true,
data: 'description'
},{
targets: 4,
title: 'type',
width: '40px',
searchable: true,
class: ['text-center'].join(' '),
data: 'type'
},{
targets: 5,
title: 'Prozess-ID&nbsp;&nbsp;&nbsp;',
width: '80px',
searchable: false,
class: 'text-right',
data: 'key'
}
]
} );
logDataTable.buttons().container().appendTo( $(this).find('.' + config.tableToolsClass));
});
});
// modal dialog is closed
logDialog.on('hidden.bs.modal', function(e) {
// clear memory -> destroy all charts
for (var key in chartData) {
if (chartData.hasOwnProperty(key)) {
chartData[key].graph = null;
// open dialog
let logDialog = bootbox.dialog({
title: 'Task-Manager',
message: contentTaskManager,
size: 'large',
buttons: {
close: {
label: 'close',
className: 'btn-default'
}
}
}
});
});
// modal dialog before hide
logDialog.on('hide.bs.modal', function(e) {
// modal dialog is shown
logDialog.on('shown.bs.modal', function(e) {
updateSyncStatus();
// destroy logTable
logDataTable.destroy(true);
logDataTable= null;
// show Morris graphs ----------------------------------------------------------
// function for chart label formation
let labelYFormat = function(y){
return Math.round(y) + 'ms';
};
for(let key in chartData) {
if(chartData.hasOwnProperty(key)) {
// create a chart for each key
let colElementGraph = $('<div>', {
class: ['col-md-6'].join(' ')
});
// graph element
let graphElement = $('<div>', {
class: config.logGraphClass
});
let graphArea = $('<div>', {
class: config.dialogDynamicAreaClass
}).append( graphElement );
// headline
let headline = $('<h4>', {
text: key
}).prepend(
$('<span>', {
class: ['txt-color', 'txt-color-grayLight'].join(' '),
text: 'Prozess-ID: '
})
);
// show update ping between function calls
let updateElement = $('<small>', {
class: ['txt-color', 'txt-color-blue', 'pull-right'].join(' ')
});
headline.append(updateElement).append('<br>');
// show average execution time
let averageElement = $('<small>', {
class: 'pull-right'
});
headline.append(averageElement);
colElementGraph.append( headline );
colElementGraph.append( graphArea );
graphArea.showLoadingAnimation();
rowElementGraphs.append( colElementGraph );
// cache DOM Elements that will be updated frequently
chartData[key].averageElement = averageElement;
chartData[key].updateElement = updateElement;
chartData[key].graph = Morris.Area({
element: graphElement,
data: [],
xkey: 'x',
ykeys: ['y'],
labels: [key],
units: 'ms',
parseTime: false,
ymin: 0,
yLabelFormat: labelYFormat,
padding: 10,
hideHover: true,
pointSize: 3,
lineColors: ['#375959'],
pointFillColors: ['#477372'],
pointStrokeColors: ['#313335'],
lineWidth: 2,
grid: false,
gridStrokeWidth: 0.3,
gridTextSize: 9,
gridTextFamily: 'Oxygen Bold',
gridTextColor: '#63676a',
behaveLikeLine: true,
goals: [],
goalLineColors: ['#66c84f'],
smooth: false,
fillOpacity: 0.3,
resize: true
});
updateLogGraph(key);
graphArea.hideLoadingAnimation();
}
}
// ------------------------------------------------------------------------------
// add dataTable buttons (extension)
let buttons = new $.fn.dataTable.Buttons( logDataTable, {
buttons: [
{
extend: 'copy',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-clipboard"></i> copy'
},{
extend: 'csv',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-download"></i> csv'
}
]
} );
logDataTable.buttons().container().appendTo( $(this).find('.' + config.tableToolsClass));
});
// modal dialog is closed
logDialog.on('hidden.bs.modal', function(e) {
// clear memory -> destroy all charts
for (let key in chartData) {
if (chartData.hasOwnProperty(key)) {
chartData[key].graph = null;
}
}
});
// modal dialog before hide
logDialog.on('hide.bs.modal', function(e) {
// destroy logTable
logDataTable.destroy(true);
logDataTable= null;
// remove event -> prevent calling this multiple times
$(this).off('hide.bs.modal');
});
// remove event -> prevent calling this multiple times
$(this).off('hide.bs.modal');
});
};
@@ -300,9 +324,9 @@ define([
/**
* updates the log graph for a log key
* @param key
* @param duration
* @param duration (if undefined -> just update graph with current data)
*/
var updateLogGraph = function(key, duration){
let updateLogGraph = function(key, duration){
// check if graph data already exist
if( !(chartData.hasOwnProperty(key))){
@@ -314,21 +338,23 @@ define([
}
// add new value
chartData[key].data.unshift(duration);
if(duration !== undefined){
chartData[key].data.unshift(duration);
}
if(chartData[key].data.length > maxGraphDataCount){
chartData[key].data = chartData[key].data.slice(0, maxGraphDataCount);
}
function getGraphData(data) {
var tempChartData = {
let tempChartData = {
data: [],
dataSum: 0,
average: 0
};
for(var x = 0; x < maxGraphDataCount; x++){
var value = 0;
for(let x = 0; x < maxGraphDataCount; x++){
let value = 0;
if(data[x]){
value = data[x];
tempChartData.dataSum = Number( (tempChartData.dataSum + value).toFixed(2) );
@@ -346,14 +372,14 @@ define([
return tempChartData;
}
var tempChartData = getGraphData(chartData[key].data);
let tempChartData = getGraphData(chartData[key].data);
// add new data to graph (Morris chart) - if is already initialized
if(chartData[key].graph !== null){
var avgElement = chartData[key].averageElement;
var updateElement = chartData[key].updateElement;
let avgElement = chartData[key].averageElement;
let updateElement = chartData[key].updateElement;
var delay = Util.getCurrentTriggerDelay( key, 0 );
let delay = Util.getCurrentTriggerDelay( key, 0 );
if(delay){
updateElement[0].textContent = ' delay: ' + delay + 'ms ';
@@ -365,8 +391,8 @@ define([
// change avg. display
avgElement[0].textContent = 'Avg. ' + tempChartData.average + 'ms';
var avgStatus = getLogStatusByDuration(key, tempChartData.average);
var avgStatusClass = Util.getLogInfo( avgStatus, 'class' );
let avgStatus = getLogStatusByDuration(key, tempChartData.average);
let avgStatusClass = Util.getLogInfo( avgStatus, 'class' );
//change avg. display class
if( !avgElement.hasClass(avgStatusClass) ){
@@ -376,7 +402,7 @@ define([
// change goals line color
if(avgStatus === 'warning'){
chartData[key].graph.options.goalLineColors = ['#e28a0d'];
$(document).setProgramStatus('problem');
$(document).setProgramStatus('slow connection');
}else{
chartData[key].graph.options.goalLineColors = ['#5cb85c'];
}
@@ -396,9 +422,8 @@ define([
* @param logDuration
* @returns {string}
*/
var getLogStatusByDuration = function(logKey, logDuration){
var logStatus = 'info';
let getLogStatusByDuration = function(logKey, logDuration){
let logStatus = 'info';
if( logDuration > Init.timer[logKey].EXECUTION_LIMIT ){
logStatus = 'warning';
}
@@ -410,9 +435,9 @@ define([
* @param logType
* @returns {string}
*/
var getLogTypeIconClass = function(logType){
let getLogTypeIconClass = function(logType){
var logIconClass = '';
let logIconClass = '';
switch(logType){
case 'client':
@@ -427,11 +452,15 @@ define([
};
/**
* init logging -> set global log event
* init logging -> set global log events
*/
var init = function(){
let init = function(){
var maxEntries = 150;
let maxEntries = 150;
$(window).on('pf:syncStatus', function(){
updateSyncStatus();
});
// set global logging listener
$(window).on('pf:log', function(e, logKey, options){
@@ -442,21 +471,19 @@ define([
options.duration &&
options.description
){
var logDescription = options.description;
var logDuration = options.duration;
var logType = options.type;
let logDescription = options.description;
let logDuration = options.duration;
let logType = options.type;
// check log status by duration
var logStatus = getLogStatusByDuration(logKey, logDuration);
var statusClass = Util.getLogInfo( logStatus, 'class' );
var typeIconClass = getLogTypeIconClass(logType);
let logStatus = getLogStatusByDuration(logKey, logDuration);
let statusClass = Util.getLogInfo( logStatus, 'class' );
let typeIconClass = getLogTypeIconClass(logType);
// update graph data
updateLogGraph(logKey, logDuration);
var logRowData = {
let logRowData = {
status: '<i class="fa fa-fw fa-circle txt-color ' + statusClass + '"></i>',
time: getLogTime(),
duration: '<span class="txt-color ' + statusClass + '">' + logDuration + '<small>ms</small></span>',
@@ -476,7 +503,7 @@ define([
}
// delete old log entries from table ---------------------------------
var rowCount = logData.length;
let rowCount = logData.length;
if( rowCount >= maxEntries ){

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ define([
'use strict';
var config = {
let config = {
logTimerCount: 3, // map log timer in seconds
// map
@@ -29,6 +29,16 @@ define([
connectionOverlayEolId: 'overlayEol' // connection overlay ID (jsPlumb)
};
/**
* get mapElement from overlay or any child of that
* @param mapOverlay
* @returns {JQuery}
*/
let getMapFromOverlay = function(mapOverlay){
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
/**
* Overlay options (all available map options shown in overlay)
* "active": (active || hover) indicated whether an icon/option
@@ -36,7 +46,7 @@ define([
* "active": Makes icon active when visible
* "hover": Make icon active on hover
*/
var options = {
let options = {
filter: {
title: 'active filter',
trigger: 'active',
@@ -62,9 +72,9 @@ define([
iconClass: ['fa', 'fa-fw', 'fa-tags'],
hoverIntent: {
over: function(e){
var mapElement = getMapFromOverlay(this);
let mapElement = getMapFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).each(function(){
var system = $(this);
let system = $(this);
// init tooltip if not already exists
if ( !system.data('bs.tooltip') ){
system.tooltip({
@@ -80,7 +90,7 @@ define([
});
},
out: function(e){
var mapElement = getMapFromOverlay(this);
let mapElement = getMapFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).tooltip('hide');
}
}
@@ -92,20 +102,20 @@ define([
iconClass: ['fa', 'fa-fw', 'fa-clock-o'],
hoverIntent: {
over: function(e){
var mapElement = getMapFromOverlay(this);
var MapUtil = require('app/map/util');
var Map = require('app/map/map');
var map = Map.getMapInstance( mapElement.data('id') );
var connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
var serverDate = Util.getServerTime();
let mapElement = getMapFromOverlay(this);
let MapUtil = require('app/map/util');
let Map = require('app/map/map');
let map = Map.getMapInstance( mapElement.data('id') );
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let serverDate = Util.getServerTime();
for (let connection of connections) {
var eolTimestamp = connection.getParameter('eolUpdated');
var eolDate = Util.convertTimestampToServerTime(eolTimestamp);
var diff = Util.getTimeDiffParts(eolDate, serverDate);
let eolTimestamp = connection.getParameter('eolUpdated');
let eolDate = Util.convertTimestampToServerTime(eolTimestamp);
let diff = Util.getTimeDiffParts(eolDate, serverDate);
// format overlay label
var label = '';
let label = '';
if(diff.days){
label += diff.days + 'd ';
}
@@ -124,11 +134,11 @@ define([
}
},
out: function(e){
var mapElement = getMapFromOverlay(this);
var MapUtil = require('app/map/util');
var Map = require('app/map/map');
var map = Map.getMapInstance( mapElement.data('id') );
var connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let mapElement = getMapFromOverlay(this);
let MapUtil = require('app/map/util');
let Map = require('app/map/map');
let map = Map.getMapInstance( mapElement.data('id') );
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
for (let connection of connections) {
connection.removeOverlay(config.connectionOverlayEolId);
@@ -138,15 +148,6 @@ define([
}
};
/**
* get mapElement from overlay or any child of that
* @param mapOverlay
* @returns {JQuery}
*/
var getMapFromOverlay = function(mapOverlay){
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
/**
* get map overlay element by type e.g. timer/counter, info - overlay
* @param overlayType
@@ -154,9 +155,9 @@ define([
*/
$.fn.getMapOverlay = function(overlayType){
var mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
let mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
var mapOverlay = null;
let mapOverlay = null;
switch(overlayType){
case 'timer':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
@@ -172,14 +173,15 @@ define([
/**
* draws the map update counter to the map overlay timer
* @param percent
* @param value
* @returns {*}
*/
$.fn.setMapUpdateCounter = function(percent, value){
var mapOverlayTimer = $(this);
let mapOverlayTimer = $(this);
// check if counter already exists
var counterChart = mapOverlayTimer.getMapCounter();
let counterChart = mapOverlayTimer.getMapCounter();
if(counterChart.length === 0){
// create new counter
@@ -212,7 +214,7 @@ define([
*/
$.fn.getMapCounter = function(){
var mapOverlayTimer = $(this);
let mapOverlayTimer = $(this);
return mapOverlayTimer.find('.' + Init.classes.pieChart.pieChartMapCounterClass);
};
@@ -222,18 +224,18 @@ define([
*/
$.fn.startMapUpdateCounter = function(){
var mapOverlayTimer = $(this);
var counterChart = mapOverlayTimer.getMapCounter();
let mapOverlayTimer = $(this);
let counterChart = mapOverlayTimer.getMapCounter();
var maxSeconds = config.logTimerCount;
let maxSeconds = config.logTimerCount;
var counterChartLabel = counterChart.find('span');
let counterChartLabel = counterChart.find('span');
var percentPerCount = 100 / maxSeconds;
let percentPerCount = 100 / maxSeconds;
// update counter
var updateChart = function(tempSeconds){
var pieChart = counterChart.data('easyPieChart');
let updateChart = function(tempSeconds){
let pieChart = counterChart.data('easyPieChart');
if(pieChart !== undefined){
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
@@ -242,13 +244,12 @@ define([
};
// main timer function is called on any counter update
var timer = function(){
let timer = function(mapUpdateCounter){
// decrease timer
var currentSeconds = counterChart.data('currentSeconds');
let currentSeconds = counterChart.data('currentSeconds');
currentSeconds--;
counterChart.data('currentSeconds', currentSeconds);
if(currentSeconds >= 0){
// update counter
updateChart(currentSeconds);
@@ -266,7 +267,7 @@ define([
};
// get current seconds (in case the timer is already running)
var currentSeconds = counterChart.data('currentSeconds');
let currentSeconds = counterChart.data('currentSeconds');
// start values for timer and chart
counterChart.data('currentSeconds', maxSeconds);
@@ -277,7 +278,9 @@ define([
currentSeconds < 0
){
// start timer
var mapUpdateCounter = setInterval(timer, 1000);
let mapUpdateCounter = setInterval(() => {
timer(mapUpdateCounter);
}, 1000);
// store counter interval
counterChart.data('interval', mapUpdateCounter);
@@ -296,14 +299,14 @@ define([
* @param viewType
*/
$.fn.updateOverlayIcon = function(option, viewType){
var mapOverlayInfo = $(this);
let mapOverlayInfo = $(this);
var showOverlay = false;
let showOverlay = false;
var mapOverlayIconClass = options[option].class;
let mapOverlayIconClass = options[option].class;
// look for the overlay icon that should be updated
var iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
let iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
if(iconElement){
if(viewType === 'show'){
@@ -335,7 +338,7 @@ define([
iconElement.data('visible', false);
// check if there is any visible icon remaining
var visibleIcons = mapOverlayInfo.find('i:visible');
let visibleIcons = mapOverlayInfo.find('i:visible');
if(visibleIcons.length > 0){
showOverlay = true;
}
@@ -364,23 +367,23 @@ define([
*/
$.fn.initMapOverlays = function(){
return this.each(function(){
var parentElement = $(this);
let parentElement = $(this);
var mapOverlayTimer = $('<div>', {
let mapOverlayTimer = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayTimerClass].join(' ')
});
parentElement.append(mapOverlayTimer);
// ---------------------------------------------------------------------------
// add map overlay info. after scrollbar is initialized
var mapOverlayInfo = $('<div>', {
let mapOverlayInfo = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayInfoClass].join(' ')
});
// add all overlay elements
for (var prop in options) {
for (let prop in options) {
if(options.hasOwnProperty(prop)){
var icon = $('<i>', {
let icon = $('<i>', {
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
}).attr('title', options[prop].title).tooltip({
placement: 'bottom',

View File

@@ -12,7 +12,7 @@ define([
], ($, Init, Util, bootbox, MapUtil) => {
'use strict';
var config = {
let config = {
systemActiveClass: 'pf-system-active' // class for an active system in a map
};
@@ -22,13 +22,13 @@ define([
*/
$.fn.showRallyPointDialog = (system) => {
requirejs(['text!templates/dialog/system_rally.html', 'mustache'], function(template, Mustache) {
var data = {
let data = {
notificationStatus: Init.notificationStatus.rallySet
};
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var rallyDialog = bootbox.dialog({
let rallyDialog = bootbox.dialog({
message: content,
title: 'Set rally point for "' + system.getSystemInfo( ['alias'] ) + '"',
buttons: {
@@ -66,9 +66,9 @@ define([
* @returns {*}
*/
$.fn.showDeleteSystemDialog = (map, systems = []) => {
var mapContainer = $( map.getContainer() );
var validDeleteSystems = [];
var activeCharacters = 0;
let mapContainer = $( map.getContainer() );
let validDeleteSystems = [];
let activeCharacters = 0;
// check if systems belong to map -> security check
for (let system of systems) {
let systemElement = $(system);
@@ -84,13 +84,13 @@ define([
}
if(validDeleteSystems.length){
var msg = '';
let msg = '';
if(validDeleteSystems.length === 1){
var deleteSystem = $(validDeleteSystems[0]);
var systemName = deleteSystem.data('name');
var systemAlias = deleteSystem.getSystemInfo( ['alias'] );
let deleteSystem = $(validDeleteSystems[0]);
let systemName = deleteSystem.data('name');
let systemAlias = deleteSystem.getSystemInfo( ['alias'] );
var systemNameStr = (systemName === systemAlias) ? '"' + systemName + '"' : '"' + systemAlias + '" (' + systemName + ')';
let systemNameStr = (systemName === systemAlias) ? '"' + systemName + '"' : '"' + systemAlias + '" (' + systemName + ')';
systemNameStr = '<span class="txt-color txt-color-warning">' + systemNameStr + '</span>';
msg = 'Delete system ' + systemNameStr + ' and all its connections?';
}else{
@@ -102,7 +102,7 @@ define([
msg += ' <span class="txt-color txt-color-warning">Warning: ' + activeCharacters + ' active characters</span>';
}
var systemDeleteDialog = bootbox.confirm(msg, result => {
let systemDeleteDialog = bootbox.confirm(msg, result => {
if(result){
deleteSystems(map, validDeleteSystems, (systems) => {
// callback function after deleted -> close dialog
@@ -130,14 +130,14 @@ define([
* @param systems
* @param callback function
*/
var deleteSystems = (map, systems = [], callback = (systems) => {}) => {
var mapContainer = $( map.getContainer() );
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
let mapContainer = $( map.getContainer() );
$.ajax({
type: 'POST',
url: Init.path.deleteSystem,
data: {
mapId: mapContainer.data('id'),
systemIds: systems.map( system => $(system).data('id') )
},
dataType: 'json',
@@ -151,7 +151,7 @@ define([
callback(this.systems);
}).fail(function(jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
@@ -162,9 +162,9 @@ define([
* @param map
* @param systems
*/
var removeSystems = (map, systems) => {
let removeSystems = (map, systems) => {
var removeSystemCallbak = function(deleteSystem){
let removeSystemCallbak = function(deleteSystem){
map.remove(deleteSystem);
};
@@ -174,7 +174,7 @@ define([
// check if system is "active"
if( system.hasClass(config.systemActiveClass) ){
// get parent Tab Content and fire clear modules event
var tabContentElement = MapUtil.getTabContentElementByMapElement( system );
let tabContentElement = MapUtil.getTabContentElementByMapElement( system );
$(tabContentElement).trigger('pf:removeSystemModules');
}

View File

@@ -9,7 +9,7 @@ define([
], function($, Init, Util) {
'use strict';
var config = {
let config = {
mapSnapToGridDimension: 20, // px for grid snapping (grid YxY)
// local storage
@@ -22,7 +22,7 @@ define([
};
// map menu options
var mapOptions = {
let mapOptions = {
mapMagnetizer: {
buttonId: Util.config.menuButtonMagnetizerId,
description: 'Magnetizer',
@@ -42,23 +42,23 @@ define([
* @param {bool} filterByUser
* @returns {Array}
*/
var getMapTypes = function(filterByUser){
var mapTypes = [];
let getMapTypes = function(filterByUser){
let mapTypes = [];
$.each(Init.mapTypes, function(prop, data){
// skip "default" type -> just for 'add' icon
if(data.label.length > 0){
var tempData = data;
let tempData = data;
tempData.name = prop;
mapTypes.push(tempData);
}
});
if(filterByUser === true){
var corporationId = Util.getCurrentUserInfo('corporationId');
var allianceId = Util.getCurrentUserInfo('allianceId');
let corporationId = Util.getCurrentUserInfo('corporationId');
let allianceId = Util.getCurrentUserInfo('allianceId');
var authorizedMapTypes = [];
let authorizedMapTypes = [];
// check if character data exists
if(corporationId > 0) {
authorizedMapTypes.push('corporation');
@@ -71,9 +71,9 @@ define([
authorizedMapTypes.push('private');
// compare "all" map types with "authorized" types
var tempMapTypes = [];
for(var i = 0; i < mapTypes.length; i++){
for(var j = 0; j < authorizedMapTypes.length; j++){
let tempMapTypes = [];
for(let i = 0; i < mapTypes.length; i++){
for(let j = 0; j < authorizedMapTypes.length; j++){
if(mapTypes[i].name === authorizedMapTypes[j]){
tempMapTypes.push(mapTypes[i]);
break;
@@ -91,10 +91,10 @@ define([
* get all available scopes for a map
* @returns {Array}
*/
var getMapScopes = function(){
var scopes = [];
let getMapScopes = function(){
let scopes = [];
$.each(Init.mapScopes, function(prop, data){
var tempData = data;
let tempData = data;
tempData.name = prop;
scopes.push(tempData);
});
@@ -108,8 +108,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getScopeInfoForMap = function(info, option){
var scopeInfo = '';
let getScopeInfoForMap = function(info, option){
let scopeInfo = '';
if(Init.mapScopes.hasOwnProperty(info)){
scopeInfo = Init.mapScopes[info][option];
}
@@ -120,7 +120,7 @@ define([
* get all available map icons
* @returns {Object[]}
*/
var getMapIcons = function(){
let getMapIcons = function(){
return Init.mapIcons;
};
@@ -130,8 +130,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getInfoForMap = function(mapType, option){
var mapInfo = '';
let getInfoForMap = function(mapType, option){
let mapInfo = '';
if(Init.mapTypes.hasOwnProperty(mapType)){
mapInfo = Init.mapTypes[mapType][option];
}
@@ -144,8 +144,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getInfoForSystem = function(info, option){
var systemInfo = '';
let getInfoForSystem = function(info, option){
let systemInfo = '';
if(Init.classes.systemInfo.hasOwnProperty(info)){
systemInfo = Init.classes.systemInfo[info][option];
}
@@ -158,8 +158,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getSystemTypeInfo = function(systemTypeId, option){
var systemTypeInfo = '';
let getSystemTypeInfo = function(systemTypeId, option){
let systemTypeInfo = '';
$.each(Init.systemType, function(prop, data){
if(systemTypeId === data.id){
systemTypeInfo = data[option];
@@ -175,8 +175,8 @@ define([
* @param option
* @returns {string}
*/
var getEffectInfoForSystem = function(effect, option){
var effectInfo = '';
let getEffectInfoForSystem = function(effect, option){
let effectInfo = '';
if( Init.classes.systemEffects.hasOwnProperty(effect) ){
effectInfo = Init.classes.systemEffects[effect][option];
}
@@ -198,9 +198,9 @@ define([
* @param {JQuery[]} systems - system DOM elements
* @returns {Array} connections - found connection, DOM elements
*/
var searchConnectionsBySystems = function(map, systems){
var connections = [];
var withBackConnection = false;
let searchConnectionsBySystems = function(map, systems){
let connections = [];
let withBackConnection = false;
$.each(systems, function(i, system){
// get connections where system is source
@@ -221,15 +221,15 @@ define([
* @param {string|string[]} type
* @returns {Array}
*/
var searchConnectionsByScopeAndType = function(map, scope, type){
var connections = [];
var scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
var typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
let searchConnectionsByScopeAndType = function(map, scope, type){
let connections = [];
let scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
let typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
map.select({scope: scopeArray}).each(function(connection){
if(typeArray.length > 0){
// filter by connection type as well...
for(var i = 0; i < typeArray.length; i++){
for(let i = 0; i < typeArray.length; i++){
if( connection.hasType(typeArray[i]) ){
connections.push(connection);
break; // don´t add same connection multiple times
@@ -250,8 +250,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getConnectionInfo = function(connectionTyp, option){
var connectionInfo = '';
let getConnectionInfo = function(connectionTyp, option){
let connectionInfo = '';
if(Init.connectionTypes.hasOwnProperty(connectionTyp)){
connectionInfo = Init.connectionTypes[connectionTyp][option];
}
@@ -265,8 +265,8 @@ define([
* @param {JQuery} systemB
* @returns {Array}
*/
var checkForConnection = function(map, systemA, systemB){
var connections = [];
let checkForConnection = function(map, systemA, systemB){
let 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}) );
@@ -279,8 +279,8 @@ define([
* @param {string} scope
* @returns {string}
*/
var getDefaultConnectionTypeByScope = function(scope){
var type = '';
let getDefaultConnectionTypeByScope = function(scope){
let type = '';
switch(scope){
case 'wh':
type = 'wh_fresh';
@@ -303,7 +303,7 @@ define([
* @param {Object} connection - jsPlumb object
* @param {string} status
*/
var setConnectionWHStatus = function(connection, status){
let setConnectionWHStatus = function(connection, status){
if(
status === 'wh_fresh' &&
connection.hasType('wh_fresh') !== true
@@ -344,13 +344,13 @@ define([
* @param {string} option
* @returns {string}
*/
var getScopeInfoForConnection = function(info, option){
var scopeInfo = '';
let getScopeInfoForConnection = function(info, option){
let scopeInfo = '';
if(Init.connectionScopes.hasOwnProperty(info)){
switch(option){
case 'connectorDefinition':
// json data in DB
var temp = '{ "data": ' + Init.connectionScopes[info][option] + '}';
let temp = '{ "data": ' + Init.connectionScopes[info][option] + '}';
scopeInfo = $.parseJSON( temp).data;
break;
default:
@@ -367,11 +367,114 @@ define([
* @param element
* @returns {*}
*/
var getTabContentElementByMapElement = function(element){
var tabContentElement = $(element).parents('.' + config.mapTabContentClass);
let getTabContentElementByMapElement = function(element){
let tabContentElement = $(element).parents('.' + config.mapTabContentClass);
return tabContentElement;
};
/**
* store mapId for current user (IndexedDB)
* @param mapId
*/
let storeDefaultMapId = function(mapId){
if(mapId > 0){
let userData = Util.getCurrentUserData();
if(
userData &&
userData.character
){
storeLocalData('character', userData.character.id, 'defaultMapId', mapId);
}
}
};
/**
* get key prefix for local storage data
* @param type
* @returns {boolean}
*/
let getLocalStoragePrefixByType = function(type){
let prefix = false;
switch(type){
case 'character': prefix = config.characterLocalStoragePrefix; break;
case 'map': prefix = config.mapLocalStoragePrefix; break;
default: prefix = config.mapLocalStoragePrefix;
}
return prefix;
};
/**
* get stored local data from client cache (IndexedDB)
* @param type
* @param objectId
* @returns {*}
*/
let getLocaleData = function(type, objectId){
if(objectId > 0){
let storageKey = getLocalStoragePrefixByType(type) + objectId;
return Util.getLocalStorage().getItem(storageKey);
}else{
console.warn('Local storage requires object id > 0');
}
};
/**
* store local config data to client cache (IndexedDB)
* @param type
* @param objectId
* @param key
* @param value
*/
let storeLocalData = function(type, objectId, key, value){
if(objectId > 0){
// get current map config
let storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
data = (data === null) ? {} : data;
// set/update value
data[this.key] = this.value;
Util.getLocalStorage().setItem(this.storageKey, data);
}.bind({
key: key,
value: value,
storageKey: storageKey
})).catch(function(err) {
// This code runs if there were any errors
console.error('Map local storage can not be accessed!');
});
}else{
console.warn('storeLocalData(): Local storage requires object id > 0');
}
};
/**
* delete local map configuration by key (IndexedDB)
* @param type
* @param objectId
* @param key
*/
let deleteLocalData = function(type, objectId, key){
if(objectId > 0){
// get current map config
let storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
if(
data &&
data.hasOwnProperty(key)
){
delete data[key];
Util.getLocalStorage().setItem(this.storageKey, data);
}
}.bind({
storageKey: storageKey
}));
}else{
console.warn('deleteLocalData(): Local storage requires object id > 0');
}
};
/**
* set or change rallyPoint for systems
* @param rallyUpdated
@@ -380,9 +483,9 @@ define([
*/
$.fn.setSystemRally = function(rallyUpdated, options){
rallyUpdated = rallyUpdated || 0;
var rallyPoke = false;
let rallyPoke = false;
var defaultOptions = {
let defaultOptions = {
poke: false,
hideNotification: false,
hideCounter: false,
@@ -390,8 +493,8 @@ define([
options = $.extend({}, defaultOptions, options);
return this.each(function(){
var system = $(this);
var rally = system.data('rallyUpdated') || 0;
let system = $(this);
let rally = system.data('rallyUpdated') || 0;
if(rallyUpdated !== rally){
// rally status changed
@@ -399,7 +502,7 @@ define([
system.getMapOverlay('timer').startMapUpdateCounter();
}
var rallyClass = getInfoForSystem('rally', 'class');
let rallyClass = getInfoForSystem('rally', 'class');
if(rallyUpdated > 0){
// new rally point set OR update system with rally information
@@ -408,7 +511,7 @@ define([
// rallyUpdated > 0 is required for poke!
rallyPoke = options.poke;
var notificationOptions = {
let notificationOptions = {
title: 'Rally Point',
text: 'System: ' + system.data('name')
};
@@ -421,13 +524,13 @@ define([
// rally saved AND poke option active
// check if desktop notification was already send
var mapId = system.data('mapid');
var systemId = system.data('id');
var promiseStore = getLocaleData('map', mapId);
let mapId = system.data('mapid');
let systemId = system.data('id');
let promiseStore = getLocaleData('map', mapId);
promiseStore.then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
var rallyPokeData = {};
let rallyPokeData = {};
if(
data &&
@@ -468,109 +571,6 @@ define([
});
};
/**
* store mapId for current user (IndexedDB)
* @param mapId
*/
var storeDefaultMapId = function(mapId){
if(mapId > 0){
var userData = Util.getCurrentUserData();
if(
userData &&
userData.character
){
storeLocalData('character', userData.character.id, 'defaultMapId', mapId);
}
}
};
/**
* get key prefix for local storage data
* @param type
* @returns {boolean}
*/
var getLocalStoragePrefixByType = function(type){
var prefix = false;
switch(type){
case 'character': prefix = config.characterLocalStoragePrefix; break;
case 'map': prefix = config.mapLocalStoragePrefix; break;
default: prefix = config.mapLocalStoragePrefix;
}
return prefix;
};
/**
* get stored local data from client cache (IndexedDB)
* @param type
* @param objectId
* @returns {*}
*/
var getLocaleData = function(type, objectId){
if(objectId > 0){
var storageKey = getLocalStoragePrefixByType(type) + objectId;
return Util.getLocalStorage().getItem(storageKey);
}else{
console.warn('Local storage requires object id > 0');
}
};
/**
* store local config data to client cache (IndexedDB)
* @param type
* @param objectId
* @param key
* @param value
*/
var storeLocalData = function(type, objectId, key, value){
if(objectId > 0){
// get current map config
var storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
data = (data === null) ? {} : data;
// set/update value
data[this.key] = this.value;
Util.getLocalStorage().setItem(this.storageKey, data);
}.bind({
key: key,
value: value,
storageKey: storageKey
})).catch(function(err) {
// This code runs if there were any errors
console.error('Map local storage can not be accessed!');
});
}else{
console.warn('storeLocalData(): Local storage requires object id > 0');
}
};
/**
* delete local map configuration by key (IndexedDB)
* @param type
* @param objectId
* @param key
*/
var deleteLocalData = function(type, objectId, key){
if(objectId > 0){
// get current map config
var storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
if(
data &&
data.hasOwnProperty(key)
){
delete data[key];
Util.getLocalStorage().setItem(this.storageKey, data);
}
}.bind({
storageKey: storageKey
}));
}else{
console.warn('deleteLocalData(): Local storage requires object id > 0');
}
};
return {
config: config,
mapOptions: mapOptions,

126
js/app/map/worker.js Normal file
View File

@@ -0,0 +1,126 @@
/**
* SharedWorker config for map
*/
define([
'app/util'
], function(Util) {
'use strict';
let config = {
};
let sharedWorker = null;
let MsgWorker = null;
let characterId = null;
/**
* get WebSocket URL for SharedWorker script
* @returns {string}
*/
let getWebSocketURL = () => {
let domain = location.host;
let workerProtocol = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
return workerProtocol + '//' + domain + '/ws/map/update';
};
/**
* get SharedWorker Script path
* @returns {string}
*/
let getWorkerScript = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/map.js';
};
/**
* get path to message object
* @returns {string}
*/
let getMessageWorkerObjectPath = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/message.js';
};
/**
* init (connect) WebSocket within SharedWorker
*/
let initSocket = () => {
let MsgWorkerInit = new MsgWorker('ws:init');
MsgWorkerInit.data({
uri: getWebSocketURL(),
characterId: characterId,
});
sharedWorker.port.postMessage(MsgWorkerInit);
};
/**
* init (start/connect) to "SharedWorker"
* -> set worker events
*/
let init = (config) => {
// set characterId that is connected with this SharedWorker PORT
characterId = parseInt(config.characterId);
// get message Class for App <=> SharedWorker MessageEvent communication
requirejs([getMessageWorkerObjectPath()], () => {
MsgWorker = window.MsgWorker;
// start/connect to "SharedWorker"
sharedWorker = new SharedWorker( getWorkerScript(), getMessageWorkerObjectPath() );
sharedWorker.port.addEventListener('message', (e) => {
let MsgWorkerMessage = e.data;
Object.setPrototypeOf(MsgWorkerMessage, MsgWorker.prototype);
switch(MsgWorkerMessage.command){
case 'ws:open':
config.callbacks.onOpen(MsgWorkerMessage);
break;
case 'ws:send':
config.callbacks.onGet(MsgWorkerMessage);
break;
case 'ws:closed':
config.callbacks.onClosed(MsgWorkerMessage);
break;
case 'ws:error':
config.callbacks.onError(MsgWorkerMessage);
break;
}
}, false);
sharedWorker.onerror = (e) => {
// could not connect to SharedWorker script -> send error back
let MsgWorkerError = new MsgWorker('sw:error');
MsgWorkerError.meta({
reason: 'Could not connect to SharedWorker: ' + getWorkerScript()
});
config.callbacks.onError(MsgWorkerError);
};
sharedWorker.port.start();
// SharedWorker initialized
let MsgWorkerInit = new MsgWorker('sw:init');
config.callbacks.onInit(MsgWorkerInit);
// startWebSocket
initSocket();
});
};
let send = (task, data) => {
let MsgWorkerSend = new MsgWorker('ws:send');
MsgWorkerSend.task(task);
MsgWorkerSend.data(data);
sharedWorker.port.postMessage(MsgWorkerSend);
};
return {
init: init,
send: send
};
});

View File

@@ -9,16 +9,17 @@ define([
'app/render',
'app/logging',
'app/page',
'app/map/worker',
'app/ui/form_element',
'app/module_map'
], function($, Init, Util, Render, Logging, Page) {
], ($, Init, Util, Render, Logging, Page, MapWorker) => {
'use strict';
/**
* main init "map" page
*/
$(function(){
$(() => {
Util.initPrototypes();
// set default AJAX config
@@ -36,14 +37,14 @@ define([
// init logging
Logging.init();
var mapModule = $('#' + Util.config.mapModuleId);
let mapModule = $('#' + Util.config.mapModuleId);
// map init load static data =======================================================
$.getJSON( Init.path.initMap, function( initData ) {
$.getJSON( Init.path.initMap, (initData) => {
if( initData.error.length > 0 ){
for(var i = 0; i < initData.error.length; i++){
for(let i = 0; i < initData.error.length; i++){
Util.showNotify({
title: initData.error[i].title,
text: initData.error[i].message,
@@ -69,207 +70,77 @@ define([
// init map module
mapModule.initMapModule();
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + jqXHR.status + ': ' + error;
}).fail(( jqXHR, status, error) => {
let reason = status + ' ' + jqXHR.status + ': ' + error;
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
});
/**
* request all map access data (tokens) -> required wor WebSocket subscription
*/
let getMapAccessData = () => {
$.getJSON( Init.path.getAccessData, ( response ) => {
if(response.status === 'OK'){
// init SharedWorker for maps
MapWorker.init({
characterId: response.data.id,
callbacks: {
onInit: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command);
},
onOpen: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
MapWorker.send( 'subscribe', response.data);
},
onGet: (MsgWorkerMessage) => {
switch(MsgWorkerMessage.task()){
case 'mapUpdate':
Util.updateCurrentMapData( MsgWorkerMessage.data() );
mapModule.updateMapModule();
break;
case 'mapAccess':
case 'mapDeleted':
Util.deleteCurrentMapData( MsgWorkerMessage.data() );
mapModule.updateMapModule();
break;
}
Util.setSyncStatus('ws:get');
},
onClosed: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
},
onError: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
}
}
});
}
});
};
getMapAccessData();
/**
* main function for init all map relevant trigger calls
*/
$.fn.initMapModule = function(){
var mapModule = $(this);
let mapModule = $(this);
// log keys ------------------------------------------------------------------------
// ajax request update map data
var logKeyServerMapData = 'UPDATE_SERVER_MAP';
// update client map data
var logKeyClientMapData = 'UPDATE_CLIENT_MAP';
// ajax request update map user data
var logKeyServerUserData = 'UPDATE_SERVER_USER_DATA';
// update client map user data
var logKeyClientUserData = 'UPDATE_CLIENT_USER_DATA';
let logKeyServerMapData = Init.performanceLogging.keyServerMapData;
let logKeyServerUserData = Init.performanceLogging.keyServerUserData;
// main update intervals/trigger (heartbeat)
var updateTimeouts = {
let updateTimeouts = {
mapUpdate: 0,
userUpdate: 0
};
var locationToggle = $('#' + Util.config.headMapTrackingId);
// ping for main map update ========================================================
var triggerMapUpdatePing = function(){
// check each execution time if map module is still available
var check = $('#' + mapModule.attr('id')).length;
if(check === 0){
// program crash stop any update
return;
}
// get updated map data
var updatedMapData = {
mapData: mapModule.getMapModuleDataForUpdate(),
getUserData: ( Util.getCurrentUserData() ) ? 0 : 1
};
// start log
Util.timeStart(logKeyServerMapData);
// store updatedMapData
$.ajax({
type: 'POST',
url: Init.path.updateMapData,
data: updatedMapData,
dataType: 'json'
}).done(function(data){
// log request time
var duration = Util.timeStop(logKeyServerMapData);
Util.log(logKeyServerMapData, {duration: duration, type: 'server', description: 'request map data'});
if(
data.error &&
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined) {
// store current user data global (cache)
Util.setCurrentUserData(data.userData);
}
if(data.mapData.length === 0){
// clear all existing maps
mapModule.clearMapModule();
// no map data available -> show "new map" dialog
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
}else{
// map data found
// start log
Util.timeStart(logKeyClientMapData);
// load/update main map module
mapModule.updateMapModule(data.mapData);
// log client map update time
duration = Util.timeStop(logKeyClientMapData);
Util.log(logKeyClientMapData, {duration: duration, type: 'client', description: 'update map'});
}
// get the current update delay (this can change if a user is inactive)
var mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
// init new trigger
updateTimeouts.mapUpdate = setTimeout(function(){
triggerMapUpdatePing();
}, mapUpdateDelay);
// initial start for the userUpdate trigger
// this should only be called at the first time!
if(updateTimeouts.userUpdate === 0){
// start user update trigger after map loaded
updateTimeouts.userUpdate = setTimeout(function(){
triggerUserUpdatePing();
}, 3000);
}
}
}).fail(handleAjaxErrorResponse);
};
// ping for user data update =======================================================
var triggerUserUpdatePing = function(){
// IMPORTANT: Get user data for ONE map that is currently visible
// On later releases this can be easy changed to "full update" all maps for a user
//
var mapIds = [];
var activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapIds = [ activeMap.data('id') ];
}
var updatedUserData = {
mapIds: mapIds,
systemData: Util.getCurrentSystemData(),
characterMapData: {
mapTracking: (locationToggle.is(':checked') ? 1 : 0) // location tracking
}
};
Util.timeStart(logKeyServerUserData);
$.ajax({
type: 'POST',
url: Init.path.updateUserData,
data: updatedUserData,
dataType: 'json'
}).done(function(data){
// log request time
var duration = Util.timeStop(logKeyServerUserData);
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
if(data.error.length > 0){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined){
// store current user data global (cache)
var userData = Util.setCurrentUserData(data.userData);
// store current map user data (cache)
if(data.mapUserData !== undefined){
Util.setCurrentMapUserData(data.mapUserData);
}
// start log
Util.timeStart(logKeyClientUserData);
// active character data found
mapModule.updateMapModuleData();
// log client user data update time
duration = Util.timeStop(logKeyClientUserData);
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
// update system info panels
if(data.system){
mapModule.updateSystemModuleData(data.system);
}
// get the current update delay (this can change if a user is inactive)
var mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
// init new trigger
updateTimeouts.userUpdate = setTimeout(function(){
triggerUserUpdatePing();
}, mapUserUpdateDelay);
}
}
}).fail(handleAjaxErrorResponse);
};
let locationToggle = $('#' + Util.config.headMapTrackingId);
/**
* Ajax error response handler function for main-ping functions
@@ -277,16 +148,16 @@ define([
* @param status
* @param error
*/
var handleAjaxErrorResponse = function(jqXHR, status, error){
let handleAjaxErrorResponse = (jqXHR, status, error) => {
// clear both main update request trigger timer
clearUpdateTimeouts();
var reason = status + ' ' + jqXHR.status + ': ' + error;
var errorData = [];
let reason = status + ' ' + jqXHR.status + ': ' + error;
let errorData = [];
if(jqXHR.responseJSON){
// handle JSON
var errorObj = $.parseJSON(jqXHR.responseText);
let errorObj = $.parseJSON(jqXHR.responseText);
if(
errorObj.error &&
@@ -306,12 +177,184 @@ define([
};
/**
* init (schedule) next MapUpdate Ping
*/
let initMapUpdatePing = () => {
// get the current update delay (this can change if a user is inactive)
let delay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
updateTimeouts.mapUpdate = setTimeout(() => {
triggerMapUpdatePing();
}, delay);
};
// ping for main map update ========================================================
let triggerMapUpdatePing = () => {
// check each interval if map module is still available
let check = $('#' + mapModule.attr('id')).length;
if(check === 0){
// program crash stop any update
return;
}
// get updated map data
let updatedMapData = {
mapData: mapModule.getMapModuleDataForUpdate(),
getUserData: ( Util.getCurrentUserData() ) ? 0 : 1
};
// check if mapUpdate trigger should be send
// -> if "syncType" === "ajax" -> send always
// -> if "syncType" === "webSocket" -> send initial AND on map changes
if(
Util.getSyncType() === 'ajax' ||
(
Util.getSyncType() === 'webSocket' &&
updatedMapData.mapData.length
)
){
// start log
Util.timeStart(logKeyServerMapData);
// store updatedMapData
$.ajax({
type: 'POST',
url: Init.path.updateMapData,
data: updatedMapData,
dataType: 'json'
}).done((data) => {
// log request time
let duration = Util.timeStop(logKeyServerMapData);
Util.log(logKeyServerMapData, {duration: duration, type: 'server', description: 'request map data'});
Util.setSyncStatus('ajax:get');
if(
data.error &&
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined) {
// store current user data global (cache)
Util.setCurrentUserData(data.userData);
}
// map data found
Util.setCurrentMapData(data.mapData);
// load/update main map module
mapModule.updateMapModule();
// get the current update delay (this can change if a user is inactive)
let mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
// init new trigger
initMapUpdatePing();
// initial start for the userUpdate trigger
// this should only be called at the first time!
if(updateTimeouts.userUpdate === 0){
// start user update trigger after map loaded
updateTimeouts.userUpdate = setTimeout(() => {
triggerUserUpdatePing();
}, 1000);
}
}
}).fail(handleAjaxErrorResponse);
}else{
// skip this mapUpdate trigger and init next one
initMapUpdatePing();
}
};
// ping for user data update =======================================================
let triggerUserUpdatePing = () => {
// IMPORTANT: Get user data for ONE map that is currently visible
// On later releases this can be easy changed to "full update" all maps for a user
//
let mapIds = [];
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapIds = [ activeMap.data('id') ];
}
let updatedUserData = {
mapIds: mapIds,
systemData: Util.getCurrentSystemData(),
characterMapData: {
mapTracking: (locationToggle.is(':checked') ? 1 : 0) // location tracking
}
};
Util.timeStart(logKeyServerUserData);
$.ajax({
type: 'POST',
url: Init.path.updateUserData,
data: updatedUserData,
dataType: 'json'
}).done((data) => {
// log request time
let duration = Util.timeStop(logKeyServerUserData);
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
if(data.error.length > 0){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined){
// store current user data global (cache)
let userData = Util.setCurrentUserData(data.userData);
// store current map user data (cache)
if(data.mapUserData !== undefined){
Util.setCurrentMapUserData(data.mapUserData);
}
// active character data found
mapModule.updateMapModuleData();
// update system info panels
if(data.system){
mapModule.updateSystemModuleData(data.system);
}
// get the current update delay (this can change if a user is inactive)
let mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
// init new trigger
updateTimeouts.userUpdate = setTimeout(() => {
triggerUserUpdatePing();
}, mapUserUpdateDelay);
}
}
}).fail(handleAjaxErrorResponse);
};
/**
* clear both main update timeouts
* -> stop program from working -> shutdown
*/
var clearUpdateTimeouts = function(){
for(var intervalKey in updateTimeouts) {
let clearUpdateTimeouts = () => {
for(let intervalKey in updateTimeouts) {
if(updateTimeouts.hasOwnProperty(intervalKey)){
clearTimeout( updateTimeouts[intervalKey] );

View File

@@ -19,7 +19,7 @@ define([
'use strict';
var config = {
let config = {
dynamicElementWrapperId: 'pf-dialog-wrapper', // parent Element for dynamic content (dialogs,..)
mapTabElementId: 'pf-map-tab-element', // id for map tab element (tabs + content)
mapTabBarId: 'pf-map-tabs', // id for map tab bar
@@ -45,15 +45,14 @@ define([
};
var mapTabChangeBlocked = false; // flag for preventing map tab switch
let mapTabChangeBlocked = false; // flag for preventing map tab switch
/**
* get all maps for a maps module
* @returns {*}
*/
$.fn.getMaps = function(){
var maps = $(this).find('.' + config.mapClass);
return maps;
return $(this).find('.' + config.mapClass);
};
/**
@@ -61,8 +60,7 @@ define([
* @returns {*}
*/
$.fn.getActiveMap = function(){
var map = $(this).find('.active.' + config.mapTabContentClass + ' .' + config.mapClass);
let map = $(this).find('.active.' + config.mapTabContentClass + ' .' + config.mapClass);
if(map.length === 0){
map = false;
@@ -92,7 +90,7 @@ define([
* @param tabContentElement
* @param callback
*/
var removeSystemModules = function(tabContentElement, callback){
let removeSystemModules = function(tabContentElement, callback){
tabContentElement.find('.' + config.moduleClass).velocity('transition.slideDownOut', {
duration: Init.animationSpeed.mapModule,
complete: function(tempElement){
@@ -109,12 +107,12 @@ define([
* clears and updates the system info element (signature table, system info,...)
* @param tabContentElement
*/
var drawSystemModules = function(tabContentElement){
var currentSystemData = Util.getCurrentSystemData();
let drawSystemModules = function(tabContentElement){
let currentSystemData = Util.getCurrentSystemData();
// get Table cell for system Info
var firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
var secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
let firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
let secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
// draw system info module
firstCell.drawSystemInfoModule(currentSystemData.mapId, currentSystemData.systemData);
@@ -138,16 +136,16 @@ define([
/**
* set observer for each module
*/
var setModuleObserver = function(){
let setModuleObserver = function(){
// toggle height for a module
$(document).off('click.toggleModuleHeight').on('click.toggleModuleHeight', '.' + config.moduleClass, function(e){
var moduleElement = $(this);
let moduleElement = $(this);
// get click position
var posX = moduleElement.offset().left;
var posY = moduleElement.offset().top;
var clickX = e.pageX - posX;
var clickY = e.pageY - posY;
let posX = moduleElement.offset().left;
let posY = moduleElement.offset().top;
let clickX = e.pageX - posX;
let clickY = e.pageY - posY;
// check for top-left click
if(clickX <= 8 && clickY <= 8){
@@ -159,7 +157,7 @@ define([
}
if(moduleElement.hasClass( config.moduleClosedClass )){
var moduleHeight = moduleElement.data('origHeight');
let moduleHeight = moduleElement.data('origHeight');
moduleElement.velocity('finish').velocity({
height: [ moduleHeight + 'px', [ 400, 15 ] ]
},{
@@ -191,15 +189,19 @@ define([
* @returns {boolean}
*/
$.fn.updateMapModuleData = function(){
var mapModule = $(this);
let mapModule = $(this);
// performance logging (time measurement)
let logKeyClientUserData = Init.performanceLogging.keyClientUserData;
Util.timeStart(logKeyClientUserData);
// get all active map elements for module
var mapElement = mapModule.getActiveMap();
let mapElement = mapModule.getActiveMap();
if(mapElement !== false){
var mapId = mapElement.data('id');
let mapId = mapElement.data('id');
var currentMapUserData = Util.getCurrentMapUserData(mapId);
let currentMapUserData = Util.getCurrentMapUserData(mapId);
// update map with current user data
if(currentMapUserData){
@@ -207,6 +209,10 @@ define([
}
}
// log client user data update time
let duration = Util.timeStop(logKeyClientUserData);
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
return true;
};
@@ -215,11 +221,11 @@ define([
* @param systemData
*/
$.fn.updateSystemModuleData = function(systemData){
var mapModule = $(this);
let mapModule = $(this);
if(systemData){
// check if current open system is still the requested info system
var currentSystemData = Util.getCurrentSystemData();
let currentSystemData = Util.getCurrentSystemData();
if(currentSystemData){
if(systemData.id === currentSystemData.systemData.id){
@@ -237,7 +243,7 @@ define([
$.fn.initContentStructure = function(){
return this.each(function(){
// init bootstrap Grid
var contentStructure = $('<div>', {
let contentStructure = $('<div>', {
class: ['row', config.mapTabContentRow].join(' ')
}).append(
$('<div>', {
@@ -259,17 +265,17 @@ define([
* @param options
* @returns {*|jQuery|HTMLElement}
*/
var getTabElement = function(options){
var tabElement = $('<div>', {
let getTabElement = function(options){
let tabElement = $('<div>', {
id: config.mapTabElementId
});
var tabBar = $('<ul>', {
let tabBar = $('<ul>', {
class: ['nav', 'nav-tabs'].join(' '),
id: options.barId
}).attr('role', 'tablist');
var tabContent = $('<div>', {
let tabContent = $('<div>', {
class: 'tab-content'
}).attr('data-map-tabs', options.barId);
@@ -284,7 +290,7 @@ define([
* @param options
*/
$.fn.updateTabData = function(options){
var tabElement = $(this);
let tabElement = $(this);
// set "main" data
tabElement.data('map-id', options.id).data('updated', options.updated);
@@ -293,17 +299,17 @@ define([
tabElement.attr('href', '#' + config.mapTabIdPrefix + options.id);
// change "map" icon
var mapIconElement = tabElement.find('.' + config.mapTabIconClass);
let mapIconElement = tabElement.find('.' + config.mapTabIconClass);
mapIconElement.removeClass().addClass([config.mapTabIconClass, 'fa', 'fa-fw', options.icon].join(' '));
// change "shared" icon
var mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
let mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
mapSharedIconElement.hide();
// check if the map is a "shared" map
if(options.access){
if(
options.access.user.length > 1 ||
options.access.character.length > 1 ||
options.access.corporation.length > 1 ||
options.access.alliance.length > 1
){
@@ -312,14 +318,14 @@ define([
}
// change map name label
var tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
let tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
tabLinkTextElement.text(options.name);
// change tabClass
var listElement = tabElement.parent();
let listElement = tabElement.parent();
// new tab classes
var tabClasses = [config.mapTabClass, options.type.classTab ];
let tabClasses = [config.mapTabClass, options.type.classTab ];
// check if tab was "active" before
if( listElement.hasClass('active') ){
@@ -332,7 +338,7 @@ define([
tabLinkTextElement.attr('title', options.type.name + ' map');
}
var mapTooltipOptions = {
let mapTooltipOptions = {
placement: 'bottom',
container: 'body',
trigger: 'hover',
@@ -353,36 +359,36 @@ define([
* @returns {{listElement: (*|void), contentElement: (*|HTMLElement)}}
*/
$.fn.addTab = function(options){
var tabElement = $(this);
var tabBar = tabElement.find('ul.nav-tabs');
var tabContent = tabElement.find('div.tab-content');
let tabElement = $(this);
let tabBar = tabElement.find('ul.nav-tabs');
let tabContent = tabElement.find('div.tab-content');
var listElement = $('<li>').attr('role', 'presentation');
let listElement = $('<li>').attr('role', 'presentation');
if(options.right === true){
listElement.addClass('pull-right');
}
// link element
var linkElement = $('<a>').attr('role', 'tab');
let linkElement = $('<a>').attr('role', 'tab');
// map icon element
var mapIconElement = $('<i>', {
let mapIconElement = $('<i>', {
class: config.mapTabIconClass
});
// map shared icon element
var mapSharedIconElement = $('<i>', {
let mapSharedIconElement = $('<i>', {
class: [config.mapTabSharedIconClass, 'fa', 'fa-fw', 'fa-share-alt'].join(' '),
title: 'shared map'
});
// text element
var textElement = $('<span>', {
let textElement = $('<span>', {
class: config.mapTabLinkTextClass
});
var newListElement = listElement.append(
let newListElement = listElement.append(
linkElement.append(mapIconElement).append(textElement).append(mapSharedIconElement)
);
@@ -392,7 +398,7 @@ define([
linkElement.updateTabData(options);
// tabs content =======================================================
var contentElement = $('<div>', {
let contentElement = $('<div>', {
id: config.mapTabIdPrefix + parseInt( options.id ),
class: [config.mapTabContentClass].join(' ')
});
@@ -414,12 +420,12 @@ define([
}
if(mapTabChangeBlocked === false){
var tabLinkElement = $(this);
var mapId = tabLinkElement.data('map-id');
let tabLinkElement = $(this);
let mapId = tabLinkElement.data('map-id');
// ignore "add" tab. no need for map change
if(mapId > 0){
var mapElement = $('#' + config.mapTabElementId).getActiveMap();
let mapElement = $('#' + config.mapTabElementId).getActiveMap();
if(mapId !== mapElement.data('id')){
// block tabs until switch is done
@@ -451,17 +457,17 @@ define([
* @param mapId
*/
$.fn.deleteTab = function(mapId){
var tabElement = $(this);
var linkElement = tabElement.find('a[href="#' + config.mapTabIdPrefix + mapId + '"]');
var deletedTabName = '';
let tabElement = $(this);
let linkElement = tabElement.find('a[href="#' + config.mapTabIdPrefix + mapId + '"]');
let deletedTabName = '';
if(linkElement.length > 0){
deletedTabName = linkElement.find('.' + config.mapTabLinkTextClass).text();
var liElement = linkElement.parent();
var contentElement = tabElement.find('div[id="' + config.mapTabIdPrefix + mapId + '"]');
let liElement = linkElement.parent();
let contentElement = tabElement.find('div[id="' + config.mapTabIdPrefix + mapId + '"]');
var findNewActiveTab = false;
let findNewActiveTab = false;
// check if liElement was active
if(liElement.hasClass('active')){
// search any remaining li element and set active
@@ -486,15 +492,15 @@ define([
* clear all active maps
*/
$.fn.clearMapModule = function(){
var mapModuleElement = $(this);
var tabMapElement = $('#' + config.mapTabElementId);
let mapModuleElement = $(this);
let tabMapElement = $('#' + config.mapTabElementId);
if(tabMapElement.length > 0){
var tabElements = mapModuleElement.getMapTabElements();
let tabElements = mapModuleElement.getMapTabElements();
for(var i = 0; i < tabElements.length; i++){
var tabElement = $(tabElements[i]);
var mapId = tabElement.data('map-id');
for(let i = 0; i < tabElements.length; i++){
let tabElement = $(tabElements[i]);
let mapId = tabElement.data('map-id');
if(mapId > 0){
tabMapElement.deleteTab(mapId);
@@ -505,43 +511,52 @@ define([
/**
* load/update map module into element (all maps)
* @param mapData
* @returns {boolean}
*/
$.fn.updateMapModule = function(mapData){
if(mapData.length === 0){
return true;
}
$.fn.updateMapModule = function(){
let mapModuleElement = $(this);
// store current map data global (cache)
// temp store current map data to prevent data-change while function execution!
var tempMapData = Util.setCurrentMapData(mapData);
let tempMapData = Util.getCurrentMapData();
var mapModuleElement = $(this);
if(tempMapData.length === 0){
// clear all existing maps
mapModuleElement.clearMapModule();
// no map data available -> show "new map" dialog
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
return true;
}
// performance logging (time measurement)
let logKeyClientMapData = Init.performanceLogging.keyClientMapData;
Util.timeStart(logKeyClientMapData);
// check if tabs module is already loaded
var tabMapElement = $('#' + config.mapTabElementId);
let tabMapElement = $('#' + config.mapTabElementId);
// check if tabs have changed
var tabsChanged = false;
let tabsChanged = false;
if(tabMapElement.length > 0){
// tab element already exists
var tabElements = mapModuleElement.getMapTabElements();
let tabElements = mapModuleElement.getMapTabElements();
// map ID that is currently active
var activeMapId = 0;
let activeMapId = 0;
// mapIds that are currently active
var activeMapIds = [];
let activeMapIds = [];
// check whether a tab/map is still active
for(var i = 0; i < tabElements.length; i++){
var tabElement = $(tabElements[i]);
var mapId = tabElement.data('map-id');
for(let i = 0; i < tabElements.length; i++){
let tabElement = $(tabElements[i]);
let mapId = tabElement.data('map-id');
if(mapId > 0){
var tabMapData = Util.getCurrentMapData(mapId);
let tabMapData = Util.getCurrentMapData(mapId);
if(tabMapData !== false){
// map data available ->
@@ -553,7 +568,7 @@ define([
}
}else{
// map data not available -> remove tab
var deletedTabName = tabMapElement.deleteTab(mapId);
let deletedTabName = tabMapElement.deleteTab(mapId);
tabsChanged = true;
@@ -569,7 +584,7 @@ define([
if( activeMapIds.indexOf( data.config.id ) === -1 ){
// add new map tab
var newTabElements = tabMapElement.addTab(data.config);
let newTabElements = tabMapElement.addTab(data.config);
// check if there is any active map yet (this is not the case
// when ALL maps are removed AND new maps are added in one call
@@ -596,11 +611,11 @@ define([
if(activeMapId === 0){
activeMapId = Util.getMapModule().getActiveMap().data('id');
}
var activeMapData = Util.getCurrentMapData(activeMapId);
let activeMapData = Util.getCurrentMapData(activeMapId);
if(activeMapData !== false){
// update active map with new mapData
var currentTabContentElement = $('#' + config.mapTabIdPrefix + activeMapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + activeMapId);
$( currentTabContentElement).loadMap( activeMapData, {} );
}
@@ -608,21 +623,21 @@ define([
// create Tab Element
tabsChanged = true;
var options = {
let options = {
barId: config.mapTabBarId
};
tabMapElement = getTabElement(options);
// add new tab for each map
for(var j = 0; j < tempMapData.length; j++){
for(let j = 0; j < tempMapData.length; j++){
var data = tempMapData[j];
let data = tempMapData[j];
tabMapElement.addTab(data.config);
}
// add "add" button
var tabAddOptions = {
let tabAddOptions = {
id: 0,
type: {
classTab: MapUtil.getInfoForMap( 'standard', 'classTab')
@@ -636,14 +651,14 @@ define([
mapModuleElement.prepend(tabMapElement);
var currentUserData = Util.getCurrentUserData();
var promiseStore = MapUtil.getLocaleData('character', currentUserData.character.id);
let currentUserData = Util.getCurrentUserData();
let promiseStore = MapUtil.getLocaleData('character', currentUserData.character.id);
promiseStore.then(function(data) {
// array key where map data is available (0 == first map found)
var mapDataIndex = 0;
let mapDataIndex = 0;
// tab dom selector
var mapKeyTabSelector = 'first';
let mapKeyTabSelector = 'first';
if(
data &&
@@ -656,7 +671,7 @@ define([
// ==============================================================
// this new created module
var tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
let tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
// set observer for manually triggered map events
tabContentElements.setTabContentObserver();
@@ -673,7 +688,7 @@ define([
if(tabsChanged === true){
// remove previous event handlers
var allTabElements = mapModuleElement.getMapTabElements();
let allTabElements = mapModuleElement.getMapTabElements();
allTabElements.off('show.bs.tab');
allTabElements.off('shown.bs.tab');
allTabElements.off('hide.bs.tab');
@@ -681,11 +696,11 @@ define([
// check for "new map" action before tap-change
allTabElements.on('show.bs.tab', function (e) {
var mapId = $(e.target).data('map-id');
let mapId = $(e.target).data('map-id');
if(mapId > 0){
// save mapId as new "default" (local storage)
var userData = MapUtil.storeDefaultMapId(mapId);
let userData = MapUtil.storeDefaultMapId(mapId);
}else{
// add new Tab selected
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
@@ -695,17 +710,17 @@ define([
// load new map right after tab-change
allTabElements.on('shown.bs.tab', function (e) {
var mapId = $(e.target).data('map-id');
var tabMapData = Util.getCurrentMapData(mapId);
let mapId = $(e.target).data('map-id');
let tabMapData = Util.getCurrentMapData(mapId);
if(tabMapData !== false){
// load map
var currentTabContentElement = $('#' + config.mapTabIdPrefix + mapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + mapId);
$( currentTabContentElement).loadMap( tabMapData, {showAnimation: true} );
// "wake up" scrollbar for map and get previous state back
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
let scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
$(scrollableElement).mCustomScrollbar( 'update');
}else{
// no map data found -> remove tab
@@ -714,20 +729,24 @@ define([
});
allTabElements.on('hide.bs.tab', function (e) {
var newMapId = $(e.relatedTarget).data('map-id');
var oldMapId = $(e.target).data('map-id');
let newMapId = $(e.relatedTarget).data('map-id');
let oldMapId = $(e.target).data('map-id');
// skip "add button"
if(newMapId > 0){
var currentTabContentElement = $('#' + config.mapTabIdPrefix + oldMapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + oldMapId);
// disable scrollbar for map that will be hidden. "freeze" current state
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
let scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
$(scrollableElement).mCustomScrollbar( 'disable' );
}
});
}
// log client map update time
let duration = Util.timeStop(logKeyClientMapData);
Util.log(logKeyClientMapData, {duration: duration, type: 'client', description: 'update map'});
return true;
};
@@ -737,14 +756,13 @@ define([
* @returns {Array}
*/
$.fn.getMapModuleDataForUpdate = function(){
// get all active map elements for module
var mapElements = $(this).getMaps();
let mapElements = $(this).getMaps();
var data = [];
for(var i = 0; i < mapElements.length; i++){
let data = [];
for(let i = 0; i < mapElements.length; i++){
// get all changed (system / connection) data from this map
var mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true});
let mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true});
if(mapData !== false){

View File

@@ -27,7 +27,7 @@ define([
'use strict';
var config = {
let config = {
// page structure slidebars-menu classes
pageId: 'sb-site',
pageSlidebarClass: 'sb-slidebar',
@@ -64,8 +64,8 @@ define([
dynamicElementWrapperId: 'pf-dialog-wrapper'
};
var programStatusCounter = 0; // current count down in s until next status change is possible
var programStatusInterval = false; // interval timer until next status change is possible
let programStatusCounter = 0; // current count down in s until next status change is possible
let programStatusInterval = false; // interval timer until next status change is possible
/**
@@ -119,7 +119,7 @@ define([
* @param title
* @returns {JQuery|*|jQuery}
*/
var getMenuHeadline = function(title){
let getMenuHeadline = function(title){
return $('<div>', {
class: 'panel-heading'
}).prepend(
@@ -211,7 +211,7 @@ define([
css: {width: '1.23em'}
})
).on('click', function(){
var fullScreenElement = $('body');
let fullScreenElement = $('body');
requirejs(['jquery', 'fullScreen'], function($) {
if($.fullscreen.isFullScreen()){
@@ -385,10 +385,9 @@ define([
* load page header
*/
$.fn.loadHeader = function(){
let pageElement = $(this);
var pageElement = $(this);
var moduleData = {
let moduleData = {
id: config.pageHeaderId,
logo: function(){
// render svg logo
@@ -403,14 +402,14 @@ define([
mapTrackingId: Util.config.headMapTrackingId
};
var headRendered = Mustache.render(TplHead, moduleData);
let headRendered = Mustache.render(TplHead, moduleData);
pageElement.prepend(headRendered);
// init header =====================================================================
// init slide menus
var slideMenu = new $.slidebars({
let slideMenu = new $.slidebars({
scrollLock: false
});
@@ -445,7 +444,7 @@ define([
});
// tracking toggle
var mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
let mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
mapTrackingCheckbox.bootstrapToggle({
size: 'mini',
on: 'on',
@@ -461,10 +460,10 @@ define([
mapTrackingCheckbox.bootstrapToggle('on');
mapTrackingCheckbox.on('change', function(e) {
var value = $(this).is(':checked');
var tracking = 'off';
var trackingText = 'Your current location will not actually be added';
var trackingType = 'info';
let value = $(this).is(':checked');
let tracking = 'off';
let trackingText = 'Your current location will not actually be added';
let trackingType = 'info';
if(value){
tracking = 'on';
trackingText = 'New connections will actually be added';
@@ -476,7 +475,7 @@ define([
// init all tooltips
var tooltipElements = $('#' + config.pageHeaderId).find('[title]');
let tooltipElements = $('#' + config.pageHeaderId).find('[title]');
tooltipElements.tooltip({
placement: 'bottom',
delay: {
@@ -492,15 +491,15 @@ define([
* load page footer
*/
$.fn.loadFooter = function(){
var pageElement = $(this);
let pageElement = $(this);
var moduleData = {
let moduleData = {
id: config.pageFooterId,
footerLicenceLinkClass: config.footerLicenceLinkClass,
currentYear: new Date().getFullYear()
};
var headRendered = Mustache.render(TplFooter, moduleData);
let headRendered = Mustache.render(TplFooter, moduleData);
pageElement.prepend(headRendered);
@@ -517,12 +516,12 @@ define([
/**
* catch all global document events
*/
var setDocumentObserver = function(){
let setDocumentObserver = function(){
// on "full-screen" change event
$(document).on('fscreenchange', function(e, state, elem){
var menuButton = $('#' + Util.config.menuButtonFullScreenId);
let menuButton = $('#' + Util.config.menuButtonFullScreenId);
if(state === true){
// full screen active
@@ -586,9 +585,9 @@ define([
$(document).on('pf:menuShowMapSettings', function(e, data){
// show map edit dialog or edit map
var mapData = false;
let mapData = false;
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapData = Util.getCurrentMapData( activeMap.data('id') );
@@ -600,9 +599,9 @@ define([
$(document).on('pf:menuDeleteMap', function(e){
// delete current active map
var mapData = false;
let mapData = false;
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapData = activeMap.getMapDataFromClient({forceData: true});
@@ -620,7 +619,7 @@ define([
$(document).on('pf:menuLogout', function(e, data){
var clearCookies = false;
let clearCookies = false;
if(
typeof data === 'object' &&
data.hasOwnProperty('clearCookies')
@@ -642,10 +641,10 @@ define([
// update header links with current map data
$(document).on('pf:updateHeaderMapData', function(e, data){
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
var userCount = 0;
var currentLocationData = {};
let userCount = 0;
let currentLocationData = {};
// show active user just for the current active map
if(
@@ -662,7 +661,7 @@ define([
// shutdown the program -> show dialog
$(document).on('pf:shutdown', function(e, data){
// show shutdown dialog
var options = {
let options = {
buttons: {
logout: {
label: '<i class="fa fa-fw fa-refresh"></i> restart',
@@ -724,21 +723,21 @@ define([
* updates the header with current user data
*/
$.fn.updateHeaderUserData = function(){
var userData = Util.getCurrentUserData();
let userData = Util.getCurrentUserData();
var userInfoElement = $('.' + config.headUserCharacterClass);
var currentCharacterId = userInfoElement.data('characterId');
var currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
var newCharacterId = 0;
var newCharacterName = '';
let userInfoElement = $('.' + config.headUserCharacterClass);
let currentCharacterId = userInfoElement.data('characterId');
let currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
let newCharacterId = 0;
let newCharacterName = '';
var userShipElement = $('.' + config.headUserShipClass);
var currentShipId = userShipElement.data('shipId');
var newShipId = 0;
var newShipName = '';
let userShipElement = $('.' + config.headUserShipClass);
let currentShipId = userShipElement.data('shipId');
let newShipId = 0;
let newShipName = '';
// function for header element toggle animation
var animateHeaderElement = function(element, callback, triggerShow){
let animateHeaderElement = function(element, callback, triggerShow){
element.show().velocity('stop').velocity({
opacity: 0
@@ -784,14 +783,14 @@ define([
updateMapTrackingToggle(userData.character.logLocation);
}
var newCharactersOptionIds = userData.characters.map(function(data){
let newCharactersOptionIds = userData.characters.map(function(data){
return data.id;
});
// update user character data ---------------------------------------------------
if(currentCharactersOptionIds.toString() !== newCharactersOptionIds.toString()){
var currentCharacterChanged = false;
let currentCharacterChanged = false;
if(currentCharacterId !== newCharacterId){
currentCharacterChanged = true;
}
@@ -814,7 +813,7 @@ define([
// update user ship data --------------------------------------------------------
if(currentShipId !== newShipId){
var showShipElement = true;
let showShipElement = true;
if(newShipId === 0){
showShipElement = false;
}
@@ -834,8 +833,8 @@ define([
* update "map tracking" toggle in header
* @param status
*/
var updateMapTrackingToggle = function(status){
var mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
let updateMapTrackingToggle = function(status){
let mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
if(status === true){
mapTrackingCheckbox.bootstrapToggle('enable');
}else{
@@ -846,7 +845,7 @@ define([
/**
* delete active character log for the current user
*/
var deleteLog = function(){
let deleteLog = function(){
$.ajax({
type: 'POST',
@@ -862,9 +861,9 @@ define([
* update the "active user" badge in header
* @param userCount
*/
var updateHeaderActiveUserCount = function(userCount){
var activeUserElement = $('.' + config.headActiveUserClass);
var badge = activeUserElement.find('.badge');
let updateHeaderActiveUserCount = function(userCount){
let activeUserElement = $('.' + config.headActiveUserClass);
let badge = activeUserElement.find('.badge');
if(badge.data('userCount') !== userCount){
badge.data('userCount', userCount);
@@ -884,13 +883,13 @@ define([
* update the "current location" element in head
* @param locationData
*/
var updateHeaderCurrentLocation = function(locationData){
var currentLocationElement = $('#' + Util.config.headCurrentLocationId);
var linkElement = currentLocationElement.find('a');
var textElement = linkElement.find('span');
let updateHeaderCurrentLocation = function(locationData){
let currentLocationElement = $('#' + Util.config.headCurrentLocationId);
let linkElement = currentLocationElement.find('a');
let textElement = linkElement.find('span');
var tempSystemName = (locationData.currentSystemName) ? locationData.currentSystemName : false;
var tempSystemId = (locationData.currentSystemId) ? locationData.currentSystemId : 0;
let tempSystemName = (locationData.currentSystemName) ? locationData.currentSystemName : false;
let tempSystemId = (locationData.currentSystemId) ? locationData.currentSystemId : 0;
if(
linkElement.data('systemName') !== tempSystemName ||
@@ -915,7 +914,7 @@ define([
/**
* shows a test notification for desktop messages
*/
var notificationTest = function(){
let notificationTest = function(){
Util.showNotify({
title: 'Test Notification',
text: 'Accept browser security question'},
@@ -930,17 +929,17 @@ define([
* set event listener if the program tab is active or not
* this is used to lower the update ping cycle to reduce server load
*/
var initTabChangeObserver = function(){
let initTabChangeObserver = function(){
// increase the timer if a user is inactive
var increaseTimer = 10000;
let increaseTimer = 10000;
// timer keys
var mapUpdateKey = 'UPDATE_SERVER_MAP';
var mapUserUpdateKey = 'UPDATE_SERVER_USER_DATA';
let mapUpdateKey = 'UPDATE_SERVER_MAP';
let mapUserUpdateKey = 'UPDATE_SERVER_USER_DATA';
// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
let hidden, visibilityChange;
if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
hidden = 'hidden';
visibilityChange = 'visibilitychange';
@@ -997,86 +996,74 @@ define([
* @param status
*/
$.fn.setProgramStatus = function(status){
var statusElement = $('.' + config.headProgramStatusClass);
var icon = statusElement.find('i');
var textElement = statusElement.find('span');
let statusElement = $('.' + config.headProgramStatusClass);
let icon = statusElement.find('i');
let textElement = statusElement.find('span');
var iconClass = false;
var textClass = false;
var text = '';
let iconClass = false;
let textClass = false;
switch(status){
case 'online':
if( ! statusElement.hasClass('txt-color-green')){
iconClass = 'fa-wifi';
textClass = 'txt-color-green';
text = 'online';
}
iconClass = 'fa-wifi';
textClass = 'txt-color-green';
break;
case 'slow connection':
case 'problem':
if( ! statusElement.hasClass('txt-color-orange')){
iconClass = 'fa-warning';
textClass = 'txt-color-orange';
text = 'problem';
}
iconClass = 'fa-warning';
textClass = 'txt-color-orange';
break;
case 'offline':
if( ! statusElement.hasClass('txt-color-red')){
iconClass = 'fa-bolt';
textClass = 'txt-color-red';
text = 'offline';
}
iconClass = 'fa-bolt';
textClass = 'txt-color-red';
break;
}
// change status, on status changed
if(iconClass !== false){
// "warnings" and "errors" always have priority -> ignore/clear interval
if(
textClass === 'txt-color-orange' ||
textClass === 'txt-color-red'
){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
// "problem" and "offline" always have priority -> ignore/clear interval
if(
status === 'problem' ||
status === 'offline'
){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
if( statusElement.data('status') !== status ){
// status has changed
if(! programStatusInterval){
if(! statusElement.hasClass(textClass) ){
let timer = function(){
// change status on first timer iteration
if(programStatusCounter === Init.timer.PROGRAM_STATUS_VISIBLE){
statusElement.velocity('stop').velocity('fadeOut', {
duration: Init.animationSpeed.headerLink,
complete: function(){
// store current status
statusElement.data('status', status);
statusElement.removeClass('txt-color-green txt-color-orange txt-color-red');
icon.removeClass('fa-wifi fa-warning fa-bolt');
statusElement.addClass(textClass);
icon.addClass(iconClass);
textElement.text(status);
}
}).velocity('fadeIn', {
duration: Init.animationSpeed.headerLink
});
}
// decrement counter
programStatusCounter -= 1000;
if(programStatusCounter <= 0){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
};
if(! programStatusInterval){
var timer = function(){
// change status on first timer iteration
if(programStatusCounter === Init.timer.PROGRAM_STATUS_VISIBLE){
statusElement.velocity('stop').velocity('fadeOut', {
duration: Init.animationSpeed.headerLink,
complete: function(){
statusElement.removeClass('txt-color-green txt-color-orange txt-color-red');
icon.removeClass('fa-wifi fa-warning fa-bolt');
statusElement.addClass(textClass);
icon.addClass(iconClass);
textElement.text(text);
}
}).velocity('fadeIn', {
duration: Init.animationSpeed.headerLink
});
}
// decrement counter
programStatusCounter -= 1000;
if(programStatusCounter <= 0){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
};
if(! programStatusInterval){
programStatusCounter = Init.timer.PROGRAM_STATUS_VISIBLE;
programStatusInterval = setInterval(timer, 1000);
}
programStatusCounter = Init.timer.PROGRAM_STATUS_VISIBLE;
programStatusInterval = setInterval(timer, 1000);
}
}
}

View File

@@ -12,7 +12,7 @@ define([
], function($, Init, Util, Render, bootbox, MapUtil) {
'use strict';
var config = {
let config = {
// map dialog
newMapDialogId: 'pf-map-dialog', // id for map settings dialog
dialogMapCreateContainerId: 'pf-map-dialog-create', // id for the "new map" container
@@ -43,11 +43,11 @@ define([
* @param filename
* @returns {string}
*/
var formatFilename = function(filename){
let formatFilename = function(filename){
filename = filename.replace(/[^a-zA-Z0-9]/g,'_');
var nowDate = new Date();
var filenameDate = nowDate.toISOString().slice(0,10).replace(/-/g, '_');
let nowDate = new Date();
let filenameDate = nowDate.toISOString().slice(0,10).replace(/-/g, '_');
return (filename + '_' + filenameDate).replace(/__/g,'_');
};
@@ -60,7 +60,7 @@ define([
$.fn.showMapSettingsDialog = function(mapData, options){
// check if dialog is already open
var mapInfoDialogElement = $('#' + config.newMapDialogId);
let mapInfoDialogElement = $('#' + config.newMapDialogId);
if(!mapInfoDialogElement.is(':visible')){
requirejs([
@@ -69,12 +69,12 @@ define([
'mustache'
], function(templateMapDialog, templateMapSettings, Mustache) {
var dialogTitle = 'Map settings';
let dialogTitle = 'Map settings';
// if there are no maps -> hide settings tab
var hideSettingsTab = false;
var hideEditTab = false;
var hideDownloadTab = false;
let hideSettingsTab = false;
let hideEditTab = false;
let hideDownloadTab = false;
if(mapData === false){
hideSettingsTab = true;
@@ -83,9 +83,9 @@ define([
}
// available map "types" for a new or existing map
var mapTypes = MapUtil.getMapTypes(true);
let mapTypes = MapUtil.getMapTypes(true);
var data = {
let data = {
scope: MapUtil.getMapScopes(),
type: mapTypes,
icon: MapUtil.getMapIcons(),
@@ -95,17 +95,17 @@ define([
};
// render "new map" tab content -------------------------------------------
var contentNewMap = Mustache.render(templateMapSettings, data);
let contentNewMap = Mustache.render(templateMapSettings, data);
// render "edit map" tab content ------------------------------------------
var contentEditMap = Mustache.render(templateMapSettings, data);
let contentEditMap = Mustache.render(templateMapSettings, data);
contentEditMap = $(contentEditMap);
// current map access info
var accessCharacter = [];
var accessCorporation = [];
var accessAlliance = [];
var deleteExpiredConnections = true;
let accessCharacter = [];
let accessCorporation = [];
let accessAlliance = [];
let deleteExpiredConnections = true;
if(mapData !== false){
// set current map information
@@ -178,20 +178,20 @@ define([
formatFilename: function(){
// format filename from "map name" (initial)
return function (mapName, render) {
var filename = render(mapName);
let filename = render(mapName);
return formatFilename(filename);
};
}
};
var contentDialog = Mustache.render(templateMapDialog, data);
let contentDialog = Mustache.render(templateMapDialog, data);
contentDialog = $(contentDialog);
// set tab content
$('#' + config.dialogMapCreateContainerId, contentDialog).html(contentNewMap);
$('#' + config.dialogMapEditContainerId, contentDialog).html(contentEditMap);
var mapInfoDialog = bootbox.dialog({
let mapInfoDialog = bootbox.dialog({
title: dialogTitle,
message: contentDialog,
buttons: {
@@ -205,15 +205,15 @@ define([
callback: function() {
// get the current active form
var form = $('#' + config.newMapDialogId).find('form').filter(':visible');
let form = $('#' + config.newMapDialogId).find('form').filter(':visible');
// validate form
form.validator('validate');
// validate select2 fields (settings tab)
form.find('select').each(function(){
var selectField = $(this);
var selectValues = selectField.val();
let selectField = $(this);
let selectValues = selectField.val();
if(selectValues.length > 0){
selectField.parents('.form-group').removeClass('has-error');
@@ -223,23 +223,23 @@ define([
});
// check whether the form is valid
var formValid = form.isValidForm();
let formValid = form.isValidForm();
if(formValid === true){
// lock dialog
var dialogContent = mapInfoDialog.find('.modal-content');
let dialogContent = mapInfoDialog.find('.modal-content');
dialogContent.showLoadingAnimation();
// get form data
var formData = form.getFormValues();
let formData = form.getFormValues();
// checkbox fix -> settings tab
if( form.find('#' + config.deleteExpiredConnectionsId).length ){
formData.deleteExpiredConnections = formData.hasOwnProperty('deleteExpiredConnections') ? parseInt( formData.deleteExpiredConnections ) : 0;
}
var requestData = {formData: formData};
let requestData = {formData: formData};
$.ajax({
type: 'POST',
@@ -257,7 +257,8 @@ define([
Util.showNotify({title: dialogTitle, text: 'Map: ' + responseData.mapData.mapData.name, type: 'success'});
// update map-tab Element
var tabLinkElement = Util.getMapModule().getMapTabElements(responseData.mapData.mapData.id);
let tabLinkElement = Util.getMapModule().getMapTabElements(responseData.mapData.mapData.id);
if(tabLinkElement.length === 1){
tabLinkElement.updateTabData(responseData.mapData.mapData);
}
@@ -266,7 +267,7 @@ define([
$(document).trigger('pf:closeMenu', [{}]);
}
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveMap', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
@@ -297,7 +298,7 @@ define([
// show form messages -------------------------------------
// get current active form(tab)
var form = $('#' + config.newMapDialogId).find('form').filter(':visible');
let form = $('#' + config.newMapDialogId).find('form').filter(':visible');
form.showFormMessage([{type: 'info', message: 'Creating new maps or change settings may take a few seconds'}]);
@@ -312,24 +313,24 @@ define([
}
// init "download tab" ========================================================================
var downloadTabElement = mapInfoDialog.find('#' + config.dialogMapDownloadContainerId);
let downloadTabElement = mapInfoDialog.find('#' + config.dialogMapDownloadContainerId);
if(downloadTabElement.length){
// tab exists
// export map data ------------------------------------------------------------------------
downloadTabElement.find('#' + config.buttonExportId).on('click', { mapData: mapData }, function(e){
var exportForm = $('#' + config.dialogMapExportFormId);
var validExportForm = exportForm.isValidForm();
let exportForm = $('#' + config.dialogMapExportFormId);
let validExportForm = exportForm.isValidForm();
if(validExportForm){
var mapElement = Util.getMapModule().getActiveMap();
let mapElement = Util.getMapModule().getActiveMap();
if(mapElement){
// IMPORTANT: Get map data from client (NOT from global mapData which is available in here)
// -> This excludes some data (e.g. wh statics)
// -> Bring export inline with main map toggle requests
var exportMapData = mapElement.getMapDataFromClient({
let exportMapData = mapElement.getMapDataFromClient({
forceData: true,
getAll: true
});
@@ -349,7 +350,7 @@ define([
// import map data ------------------------------------------------------------------------
// check if "FileReader" API is supported
var importFormElement = downloadTabElement.find('#' + config.dialogMapImportFormId);
let importFormElement = downloadTabElement.find('#' + config.dialogMapImportFormId);
if(window.File && window.FileReader && window.FileList && window.Blob){
// show file info in UI
@@ -357,14 +358,14 @@ define([
e.stopPropagation();
e.preventDefault();
var infoContainerElement = importFormElement.find('#' + config.dialogMapImportInfoId);
let infoContainerElement = importFormElement.find('#' + config.dialogMapImportInfoId);
infoContainerElement.hide().empty();
importFormElement.hideFormMessage('all');
var output = [];
var files = e.target.files;
let output = [];
let files = e.target.files;
for (var i = 0, f; !!(f = files[i]); i++) {
for (let i = 0, f; !!(f = files[i]); i++) {
output.push(( i + 1 ) + '. file: ' + f.name + ' - ' +
f.size + ' bytes; last modified: ' +
f.lastModifiedDate.toLocaleDateString() );
@@ -378,14 +379,14 @@ define([
});
// drag&drop
var importData = {};
let importData = {};
importData.mapData = [];
var files = [];
var filesCount = 0;
var filesCountFail = 0;
let files = [];
let filesCount = 0;
let filesCountFail = 0;
// onLoad for FileReader API
var readerOnLoad = function(readEvent) {
let readerOnLoad = function(readEvent) {
// get file content
try{
@@ -404,13 +405,13 @@ define([
}
};
var handleDragOver = function(dragEvent) {
let handleDragOver = function(dragEvent) {
dragEvent.stopPropagation();
dragEvent.preventDefault();
dragEvent.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
};
var handleFileSelect = function(evt){
let handleFileSelect = function(evt){
evt.stopPropagation();
evt.preventDefault();
@@ -421,14 +422,14 @@ define([
files = evt.dataTransfer.files; // FileList object.
for (var file; !!(file = files[filesCount]); filesCount++){
var reader = new FileReader();
for (let file; !!(file = files[filesCount]); filesCount++){
let reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsText(file);
}
};
var dropZone = downloadTabElement.find('.' + config.dragDropElementClass);
let dropZone = downloadTabElement.find('.' + config.dragDropElementClass);
dropZone[0].addEventListener('dragover', handleDragOver, false);
dropZone[0].addEventListener('drop', handleFileSelect, false);
@@ -436,19 +437,19 @@ define([
downloadTabElement.find('#' + config.buttonImportId).on('click', function(e) {
importFormElement.validator('validate');
var validImportForm = importFormElement.isValidForm();
let validImportForm = importFormElement.isValidForm();
if(validImportForm){
importData = importFormElement.getFormValues();
importData.mapData = [];
var fileElement = downloadTabElement.find('#' + config.fieldImportId);
let fileElement = downloadTabElement.find('#' + config.fieldImportId);
files = fileElement[0].files;
filesCount = 0;
filesCountFail = 0;
for (var file; !!(file = files[filesCount]); filesCount++){
var reader = new FileReader();
for (let file; !!(file = files[filesCount]); filesCount++){
let reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsText(file);
}
@@ -462,9 +463,9 @@ define([
// events for tab change
mapInfoDialog.find('.navbar a').on('shown.bs.tab', function(e){
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
let selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
let selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
let selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
if($(e.target).attr('href') === '#' + config.dialogMapSettingsContainerId){
// "settings" tab
@@ -498,13 +499,13 @@ define([
* import new map(s) data
* @param importData
*/
var importMaps = function(importData){
let importMaps = function(importData){
var importForm = $('#' + config.dialogMapImportFormId);
let importForm = $('#' + config.dialogMapImportFormId);
importForm.hideFormMessage('all');
// lock dialog
var dialogContent = importForm.parents('.modal-content');
let dialogContent = importForm.parents('.modal-content');
dialogContent.showLoadingAnimation();
$.ajax({
@@ -525,7 +526,7 @@ define([
Util.showNotify({title: 'Import finished', text: 'Map(s) imported', type: 'success'});
}
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': importMap', text: reason, type: 'error'});
}).always(function() {
importForm.find('input, select').resetFormFields().trigger('change');
@@ -540,9 +541,9 @@ define([
*/
$.fn.setExportMapData = function(mapData){
var fieldExport = $('#' + config.fieldExportId);
var filename = '';
var mapDataEncoded = '';
let fieldExport = $('#' + config.fieldExportId);
let filename = '';
let mapDataEncoded = '';
if(fieldExport.length){
filename = fieldExport.val();
@@ -553,7 +554,7 @@ define([
}
return this.each(function(){
var exportButton = $(this);
let exportButton = $(this);
exportButton.attr('href', 'data:' + mapDataEncoded);
exportButton.attr('download', filename + '.json');
});
@@ -564,11 +565,11 @@ define([
* init select2 fields within the settings dialog
* @param mapInfoDialog
*/
var initSettingsSelectFields = function(mapInfoDialog){
let initSettingsSelectFields = function(mapInfoDialog){
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
let selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
let selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
let selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
// init character select live search
selectElementCharacter.initAccessSelect({
@@ -595,12 +596,11 @@ define([
*/
$.fn.showDeleteMapDialog = function(mapData){
var mapName = mapData.config.name;
let mapName = mapData.config.name;
var mapDeleteDialog = bootbox.confirm('Delete map "' + mapName + '"?', function(result){
let mapDeleteDialog = bootbox.confirm('Delete map "' + mapName + '"?', function(result){
if(result){
var data = {mapData: mapData.config};
let data = {mapData: mapData.config};
$.ajax({
type: 'POST',
@@ -609,12 +609,12 @@ define([
dataType: 'json'
}).done(function(data){
Util.showNotify({title: 'Map deleted', text: 'Map: ' + mapName, type: 'success'});
$(mapDeleteDialog).modal('hide');
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteMap', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
}).always(function() {
$(mapDeleteDialog).modal('hide');
});
return false;

View File

@@ -11,7 +11,7 @@ define([
], function($, Init, Util, bootbox, MapUtil) {
'use strict';
var config = {
let config = {
// module info
moduleClass: 'pf-module', // class for each module
@@ -39,7 +39,7 @@ define([
};
// cache for system routes
var cache = {
let cache = {
systemRoutes: {} // jump information between solar systems
};
@@ -48,17 +48,17 @@ define([
* @param context
* @param routesData
*/
var callbackAddRouteRow = function(context, routesData){
let callbackAddRouteRow = function(context, routesData){
if(routesData.length > 0){
for(var i = 0; i < routesData.length; i++){
var routeData = routesData[i];
for(let i = 0; i < routesData.length; i++){
let routeData = routesData[i];
// format routeData
var rowData = formatRouteData(routeData);
let rowData = formatRouteData(routeData);
if(rowData.route){
var cacheKey = routeData.systemFromData.name.toLowerCase() +
let cacheKey = routeData.systemFromData.name.toLowerCase() +
'_' + routeData.systemToData.name.toLowerCase();
// update route cache
@@ -67,7 +67,7 @@ define([
updated: Util.getServerTime().getTime() / 1000
};
var rowElement = addRow(context, rowData);
let rowElement = addRow(context, rowData);
rowElement.initTooltips({
container: 'body'
@@ -86,15 +86,15 @@ define([
* @param rowData
* @returns {*}
*/
var addRow = function(context, rowData){
var dataTable = context.dataTable;
var rowElement = null;
var row = null;
var animationStatus = 'changed';
let addRow = function(context, rowData){
let dataTable = context.dataTable;
let rowElement = null;
let row = null;
let animationStatus = 'changed';
// search for an existing row (e.g. on mass "table refresh" [all routes])
// get rowIndex where column 1 (equals to "systemToData.name") matches rowData.systemToData.name
var indexes = dataTable.rows().eq(0).filter( function (rowIdx) {
let indexes = dataTable.rows().eq(0).filter( function (rowIdx) {
return (dataTable.cell(rowIdx, 1 ).data().name === rowData.systemToData.name);
});
@@ -122,17 +122,43 @@ define([
return rowElement;
};
/**
* requests route data from eveCentral API and execute callback
* @param requestData
* @param context
* @param callback
*/
let getRouteData = function(requestData, context, callback){
context.moduleElement.showLoadingAnimation();
$.ajax({
url: Init.path.searchRoute,
type: 'POST',
dataType: 'json',
data: requestData,
context: context
}).done(function(routesData){
this.moduleElement.hideLoadingAnimation();
// execute callback
callback(this, routesData.routesData);
});
};
/**
* update complete routes table (refresh all)
* @param moduleElement
* @param dataTable
*/
var updateRoutesTable = function(moduleElement, dataTable){
var context = {
let updateRoutesTable = function(moduleElement, dataTable){
let context = {
moduleElement: moduleElement,
dataTable: dataTable
};
var routeData = [];
let routeData = [];
dataTable.rows().every( function() {
routeData.push( getRouteRequestDataFromRowData( this.data() ));
@@ -146,7 +172,7 @@ define([
* @param {Object} rowData
* @returns {Object}
*/
var getRouteRequestDataFromRowData = function(rowData){
let getRouteRequestDataFromRowData = function(rowData){
return {
mapIds: (rowData.hasOwnProperty('mapIds')) ? rowData.mapIds : [],
systemFromData: (rowData.hasOwnProperty('systemFromData')) ? rowData.systemFromData : {},
@@ -157,7 +183,8 @@ define([
wormholes: (rowData.hasOwnProperty('wormholes')) ? rowData.wormholes | 0 : 1,
wormholesReduced: (rowData.hasOwnProperty('wormholesReduced')) ? rowData.wormholesReduced | 0 : 1,
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
safer: (rowData.hasOwnProperty('safer')) ? rowData.safer.value | 0 : 0
};
};
@@ -165,12 +192,12 @@ define([
* show route dialog. User can search for systems and jump-info for each system is added to a data table
* @param dialogData
*/
var showFindRouteDialog = function(dialogData){
let showFindRouteDialog = function(dialogData){
var mapSelectOptions = [];
var currentMapData = Util.getCurrentMapData();
let mapSelectOptions = [];
let currentMapData = Util.getCurrentMapData();
if(currentMapData !== false){
for(var i = 0; i < currentMapData.length; i++){
for(let i = 0; i < currentMapData.length; i++){
mapSelectOptions.push({
id: currentMapData[i].config.id,
name: currentMapData[i].config.name,
@@ -178,7 +205,7 @@ define([
});
}
}
var data = {
let data = {
id: config.routeDialogId,
selectClass: config.systemDialogSelectClass,
mapSelectId: config.mapSelectId,
@@ -188,9 +215,9 @@ define([
requirejs(['text!templates/dialog/route.html', 'mustache'], function(template, Mustache) {
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var findRouteDialog = bootbox.dialog({
let findRouteDialog = bootbox.dialog({
title: 'Route finder',
message: content,
show: false,
@@ -206,15 +233,15 @@ define([
// add new route to route table
// get form Values
var form = $('#' + config.routeDialogId).find('form');
let form = $('#' + config.routeDialogId).find('form');
var routeDialogData = $(form).getFormValues();
let routeDialogData = $(form).getFormValues();
// validate form
form.validator('validate');
// check whether the form is valid
var formValid = form.isValidForm();
let formValid = form.isValidForm();
if(formValid === false){
// don't close dialog
@@ -222,18 +249,18 @@ define([
}
// get all system data from select2
var systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
let systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
if(
systemSelectData &&
systemSelectData.length === 1
){
var context = {
let context = {
moduleElement: dialogData.moduleElement,
dataTable: dialogData.dataTable
};
var requestData = {
let requestData = {
routeData: [{
mapIds: routeDialogData.mapIds,
systemFromData: dialogData.systemFromData,
@@ -264,7 +291,7 @@ define([
setDialogObserver( $(this) );
// init map select ----------------------------------------------------------------
var mapSelect = $(this).find('#' + config.mapSelectId);
let mapSelect = $(this).find('#' + config.mapSelectId);
mapSelect.initMapSelect();
});
@@ -273,7 +300,7 @@ define([
// init system select live search ------------------------------------------------
// -> add some delay until modal transition has finished
var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'name'});
});
@@ -282,6 +309,69 @@ define([
});
};
/**
* draw route table
* @param mapId
* @param moduleElement
* @param systemFromData
* @param routesTable
* @param systemsTo
*/
let drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
let requestRouteData = [];
let currentTimestamp = Util.getServerTime().getTime();
// Skip some routes from search
// -> this should help to throttle requests (heavy CPU load for route calculation)
let defaultRoutesCount = Init.routeSearch.defaultCount;
for(let i = 0; i < systemsTo.length; i++){
let systemToData = systemsTo[i];
if(systemFromData.name !== systemToData.name){
let cacheKey = 'route_' + mapId + '_' + systemFromData.name.toUpperCase() + '_' + systemToData.name.toUpperCase();
if(
cache.systemRoutes.hasOwnProperty(cacheKey) &&
Math.round(
( currentTimestamp - (new Date( cache.systemRoutes[cacheKey].updated * 1000).getTime())) / 1000
) <= config.routeCacheTTL
){
// route data is cached (client side)
let context = {
dataTable: routesTable
};
addRow(context, cache.systemRoutes[cacheKey].data);
}else{
// get route data
let searchData = {
mapIds: [mapId],
systemFromData: systemFromData,
systemToData: systemToData,
skipSearch: requestRouteData.length >= defaultRoutesCount
};
requestRouteData.push( getRouteRequestDataFromRowData( searchData ));
}
}
}
// check if routes data is not cached and is requested
if(requestRouteData.length > 0){
let contextData = {
moduleElement: moduleElement,
dataTable: routesTable
};
let requestData = {
routeData: requestRouteData
};
getRouteData(requestData, contextData, callbackAddRouteRow);
}
};
/**
* show route settings dialog
* @param dialogData
@@ -289,12 +379,12 @@ define([
* @param systemFromData
* @param routesTable
*/
var showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
let showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
var promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
let promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
promiseStore.then(function(dataStore) {
// selected systems (if already stored)
var systemSelectOptions = [];
let systemSelectOptions = [];
if(
dataStore &&
dataStore.routes
@@ -303,9 +393,9 @@ define([
}
// max count of "default" target systems
var maxSelectionLength = Init.routeSearch.maxDefaultCount;
let maxSelectionLength = Init.routeSearch.maxDefaultCount;
var data = {
let data = {
id: config.routeSettingsDialogId,
selectClass: config.systemDialogSelectClass,
systemSelectOptions: systemSelectOptions,
@@ -313,9 +403,9 @@ define([
};
requirejs(['text!templates/dialog/route_settings.html', 'mustache'], function(template, Mustache) {
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var settingsDialog = bootbox.dialog({
let settingsDialog = bootbox.dialog({
title: 'Route settings',
message: content,
show: false,
@@ -328,10 +418,10 @@ define([
label: '<i class="fa fa-fw fa-check"></i>&nbsp;save',
className: 'btn-success',
callback: function () {
var form = this.find('form');
let form = this.find('form');
// get all system data from select2
var systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
var systemsTo = [];
let systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
let systemsTo = [];
if( systemSelectData.length > 0 ){
systemsTo = formSystemSelectData(systemSelectData);
@@ -353,7 +443,7 @@ define([
// init default system select -----------------------------------------------------
// -> add some delay until modal transition has finished
var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'name', maxSelectionLength: maxSelectionLength});
});
@@ -368,10 +458,10 @@ define([
* @param {Array} data
* @returns {Array}
*/
var formSystemSelectData = function(data){
var formattedData = [];
let formSystemSelectData = function(data){
let formattedData = [];
for(let i = 0; i < data.length; i++){
var tmpData = data[i];
let tmpData = data[i];
formattedData.push({
name: tmpData.id,
@@ -386,21 +476,21 @@ define([
* set event observer for route finder dialog
* @param routeDialog
*/
var setDialogObserver = function(routeDialog){
var wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
var wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
var wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
var wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
let setDialogObserver = function(routeDialog){
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
// store current "checked" state for each box ---------------------------------------------
var storeCheckboxStatus = function(){
let storeCheckboxStatus = function(){
wormholeReducedCheckbox.data('selectState', wormholeReducedCheckbox.prop('checked'));
wormholeCriticalCheckbox.data('selectState', wormholeCriticalCheckbox.prop('checked'));
wormholeEolCheckbox.data('selectState', wormholeEolCheckbox.prop('checked'));
};
// on wormhole checkbox change ------------------------------------------------------------
var onWormholeCheckboxChange = function(){
let onWormholeCheckboxChange = function(){
if( $(this).is(':checked') ){
wormholeReducedCheckbox.prop('disabled', false);
@@ -429,37 +519,12 @@ define([
onWormholeCheckboxChange();
};
/**
* requests route data from eveCentral API and execute callback
* @param requestData
* @param context
* @param callback
*/
var getRouteData = function(requestData, context, callback){
context.moduleElement.showLoadingAnimation();
$.ajax({
url: Init.path.searchRoute,
type: 'POST',
dataType: 'json',
data: requestData,
context: context
}).done(function(routesData){
this.moduleElement.hideLoadingAnimation();
// execute callback
callback(this, routesData.routesData);
});
};
/**
* format route data from API request into dataTable row format
* @param routeData
* @returns {{}}
*/
var formatRouteData = function(routeData){
let formatRouteData = function(routeData){
/**
* get status icon for route
@@ -487,14 +552,18 @@ define([
// 0: not found
// 1: round (OK)
// 2: not searched
var routeStatus = routeData.skipSearch ? 2 : 0;
let routeStatus = routeData.skipSearch ? 2 : 0;
var reloadButton = '<i class="fa ' + ['fa-refresh'].join(' ') + '"></i>';
var searchButton = '<i class="fa ' + ['fa-search-plus '].join(' ') + '"></i>';
var deleteButton = '<i class="fa ' + ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
// button class for "safer" routes
let saferButtonClass = routeData.safer ? 'txt-color-success' : '';
let saferButton = '<i class="fa ' + ['fa-shield', 'txt-color', saferButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fa ' + ['fa-refresh'].join(' ') + '"></i>';
let searchButton = '<i class="fa ' + ['fa-search-plus '].join(' ') + '"></i>';
let deleteButton = '<i class="fa ' + ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
// default row data (e.g. no route found)
var tableRowData = {
let tableRowData = {
systemFromData: routeData.systemFromData,
systemToData: routeData.systemToData,
jumps: {
@@ -512,6 +581,10 @@ define([
wormholesReduced: routeData.wormholesReduced,
wormholesCritical: routeData.wormholesCritical,
wormholesEOL: routeData.wormholesEOL,
safer: {
value: routeData.safer,
button: saferButton
},
reload: {
button: routeData.skipSearch ? searchButton : reloadButton
},
@@ -530,14 +603,14 @@ define([
routeStatus = 1;
// add route Data
var jumpData = [];
var avgSecTemp = 0;
let jumpData = [];
let avgSecTemp = 0;
// loop all systems on this route
for(var i = 0; i < routeData.route.length; i++){
for(let i = 0; i < routeData.route.length; i++){
let routeNodeData = routeData.route[i];
// format system name (camelCase)
let systemName = routeNodeData.system.charAt(0).toUpperCase() + routeNodeData.system.slice(1).toLowerCase();
// format system name
let systemName = routeNodeData.system;
let systemSec = Number(routeNodeData.security).toFixed(1).toString();
let tempSystemSec = systemSec;
@@ -565,14 +638,14 @@ define([
}
}
var avgSec = ( avgSecTemp / (routeData.route.length - 1)).toFixed(2);
var avgSecForClass = Number(avgSec).toFixed(1);
let avgSec = ( avgSecTemp / (routeData.route.length - 1)).toFixed(2);
let avgSecForClass = Number(avgSec).toFixed(1);
if(avgSecForClass <= 0){
avgSecForClass = '0.0';
}
var avgSecClass = config.systemSecurityClassPrefix + avgSecForClass.toString().replace('.', '-');
let avgSecClass = config.systemSecurityClassPrefix + avgSecForClass.toString().replace('.', '-');
tableRowData.jumps = {
value: routeData.routeJumps,
@@ -599,15 +672,15 @@ define([
* get the route finder moduleElement
* @returns {*}
*/
var getModule = function(){
let getModule = function(){
// create new module container
var moduleElement = $('<div>', {
let moduleElement = $('<div>', {
class: [config.moduleClass, config.systemRouteModuleClass].join(' ')
});
// headline toolbar icons
var headlineToolbar = $('<h5>', {
let headlineToolbar = $('<h5>', {
class: 'pull-right'
}).append(
$('<i>', {
@@ -627,7 +700,7 @@ define([
moduleElement.append(headlineToolbar);
// headline
var headline = $('<h5>', {
let headline = $('<h5>', {
class: 'pull-left',
text: 'Routes'
});
@@ -635,14 +708,14 @@ define([
moduleElement.append(headline);
// crate new route table
var table = $('<table>', {
let table = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border', config.systemInfoRoutesTableClass].join(' ')
});
moduleElement.append( $(table) );
// init empty table
var routesTable = table.DataTable( {
let routesTable = table.DataTable( {
paging: false,
ordering: true,
order: [[ 2, 'asc' ], [ 0, 'asc' ]],
@@ -711,41 +784,35 @@ define([
data: 'route'
},{
targets: 5,
title: '',
title: '<i title="search safer route (HS)" data-toggle="tooltip" class="fa fa-shield text-right"></i>',
orderable: false,
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'reload',
data: 'safer',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
var tempTableApi = this.api();
let tempTableApi = this.api();
$(cell).on('click', function(e) {
// get current row data (important!)
// -> "rowData" param is not current state, values are "on createCell()" state
rowData = tempTableApi.row( $(cell).parents('tr')).data();
let routeData = getRouteRequestDataFromRowData( rowData );
var context = {
// overwrite some params
routeData.skipSearch = 0;
routeData.safer = 1 - routeData.safer; // toggle
let context = {
moduleElement: moduleElement,
dataTable: tempTableApi
};
var requestData = {
routeData: [{
mapIds: rowData.mapIds,
systemFromData: rowData.systemFromData,
systemToData: rowData.systemToData,
skipSearch: 0,
stargates: rowData.stargates ? 1 : 0,
jumpbridges: rowData.jumpbridges ? 1 : 0,
wormholes: rowData.wormholes ? 1 : 0,
wormholesReduced: rowData.wormholesReduced ? 1 : 0,
wormholesCritical: rowData.wormholesCritical ? 1 : 0,
wormholesEOL: rowData.wormholesEOL ? 1 : 0
}]
let requestData = {
routeData: [routeData]
};
getRouteData(requestData, context, callbackAddRouteRow);
@@ -758,14 +825,49 @@ define([
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'reload',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
let tempTableApi = this.api();
$(cell).on('click', function(e) {
// get current row data (important!)
// -> "rowData" param is not current state, values are "on createCell()" state
rowData = tempTableApi.row( $(cell).parents('tr')).data();
let routeData = getRouteRequestDataFromRowData( rowData );
// overwrite some params
routeData.skipSearch = 0;
let context = {
moduleElement: moduleElement,
dataTable: tempTableApi
};
let requestData = {
routeData: [routeData]
};
getRouteData(requestData, context, callbackAddRouteRow);
});
}
},{
targets: 7,
title: '',
orderable: false,
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'clear',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
var tempTableElement = this;
let tempTableElement = this;
var confirmationSettings = {
let confirmationSettings = {
container: 'body',
placement: 'left',
btnCancelClass: 'btn btn-sm btn-default',
@@ -776,7 +878,7 @@ define([
btnOkLabel: 'delete',
btnOkIcon: 'fa fa-fw fa-close',
onConfirm : function(e, target){
var deleteRowElement = $(cell).parents('tr');
let deleteRowElement = $(cell).parents('tr');
tempTableElement.api().rows(deleteRowElement).remove().draw();
}
};
@@ -788,14 +890,14 @@ define([
],
drawCallback: function(settings){
var animationRows = this.api().rows().nodes().to$().filter(function() {
let animationRows = this.api().rows().nodes().to$().filter(function() {
return (
$(this).data('animationStatus') ||
$(this).data('animationTimer')
);
});
for(var i = 0; i < animationRows.length; i++){
for(let i = 0; i < animationRows.length; i++){
$(animationRows[i]).pulseTableRow($(animationRows[i]).data('animationStatus'));
$(animationRows[i]).removeData('animationStatus');
}
@@ -805,7 +907,7 @@ define([
});
// init tooltips for this module
var tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
let tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
tooltipElements.tooltip({
container: 'body'
});
@@ -819,19 +921,19 @@ define([
* @param options
*/
$.fn.initSystemPopover = function(options){
var elements = $(this);
var eventNamespace = 'hideSystemPopup';
var systemToData = options.systemToData;
let elements = $(this);
let eventNamespace = 'hideSystemPopup';
let systemToData = options.systemToData;
requirejs(['text!templates/tooltip/system_popover.html', 'mustache'], function (template, Mustache) {
var data = {
let data = {
systemToData: systemToData
};
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
elements.each(function() {
var element = $(this);
let element = $(this);
// destroy "popover" and remove "click" event for animation
element.popover('destroy').off();
@@ -859,11 +961,11 @@ define([
// set link observer "on shown" event
elements.on('shown.bs.popover', function () {
var popoverRoot = $(this);
let popoverRoot = $(this);
popoverRoot.data('bs.popover').tip().find('a').on('click', function(){
// hint: "data" attributes should be in lower case!
var systemData = {
let systemData = {
name: $(this).data('name'),
systemId: $(this).data('systemid')
};
@@ -883,16 +985,16 @@ define([
* @param mapId
* @param systemData
*/
var initModule = function(moduleElement, mapId, systemData){
let initModule = function(moduleElement, mapId, systemData){
var systemFromData = {
let systemFromData = {
name: systemData.name,
systemId: systemData.systemId
};
var routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
let routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
var routesTable = routesTableElement.DataTable();
let routesTable = routesTableElement.DataTable();
// init refresh routes --------------------------------------------------------------------
moduleElement.find('.' + config.systemModuleHeadlineIconRefresh).on('click', function(e){
@@ -907,7 +1009,7 @@ define([
// max routes limit reached -> show warning
Util.showNotify({title: 'Route limit reached', text: 'Serch is limited by ' + maxRouteSearchLimit, type: 'warning'});
}else{
var dialogData = {
let dialogData = {
moduleElement: moduleElement,
mapId: mapId,
systemFromData: systemFromData,
@@ -922,7 +1024,7 @@ define([
// init settings dialog -------------------------------------------------------------------
moduleElement.find('.' + config.systemModuleHeadlineIconSettings).on('click', function(e){
var dialogData = {
let dialogData = {
mapId: mapId
};
@@ -930,10 +1032,10 @@ define([
});
// fill routesTable with data -------------------------------------------------------------
var promiseStore = MapUtil.getLocaleData('map', mapId);
let promiseStore = MapUtil.getLocaleData('map', mapId);
promiseStore.then(function(dataStore) {
// selected systems (if already stored)
var systemsTo = [{
let systemsTo = [{
name: 'Jita',
systemId: 30000142
}];
@@ -950,69 +1052,6 @@ define([
};
/**
* draw route table
* @param mapId
* @param moduleElement
* @param systemFromData
* @param routesTable
* @param systemsTo
*/
var drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
var requestRouteData = [];
var currentTimestamp = Util.getServerTime().getTime();
// Skip some routes from search
// -> this should help to throttle requests (heavy CPU load for route calculation)
var defaultRoutesCount = Init.routeSearch.defaultCount;
for(var i = 0; i < systemsTo.length; i++){
var systemToData = systemsTo[i];
if(systemFromData.name !== systemToData.name){
var cacheKey = 'route_' + mapId + '_' + systemFromData.name.toUpperCase() + '_' + systemToData.name.toUpperCase();
if(
cache.systemRoutes.hasOwnProperty(cacheKey) &&
Math.round(
( currentTimestamp - (new Date( cache.systemRoutes[cacheKey].updated * 1000).getTime())) / 1000
) <= config.routeCacheTTL
){
// route data is cached (client side)
var context = {
dataTable: routesTable
};
addRow(context, cache.systemRoutes[cacheKey].data);
}else{
// get route data
var searchData = {
mapIds: [mapId],
systemFromData: systemFromData,
systemToData: systemToData,
skipSearch: requestRouteData.length >= defaultRoutesCount
};
requestRouteData.push( getRouteRequestDataFromRowData( searchData ));
}
}
}
// check if routes data is not cached and is requested
if(requestRouteData.length > 0){
var contextData = {
moduleElement: moduleElement,
dataTable: routesTable
};
var requestData = {
routeData: requestRouteData
};
getRouteData(requestData, contextData, callbackAddRouteRow);
}
};
/**
* updates an dom element with the system route module
* @param mapId
@@ -1020,10 +1059,10 @@ define([
*/
$.fn.drawSystemRouteModule = function(mapId, systemData){
var parentElement = $(this);
let parentElement = $(this);
// show route module
var showModule = function(moduleElement){
let showModule = function(moduleElement){
if(moduleElement){
moduleElement.css({ opacity: 0 });
parentElement.append(moduleElement);
@@ -1039,7 +1078,7 @@ define([
};
// check if module already exists
var moduleElement = parentElement.find('.' + config.systemRouteModuleClass);
let moduleElement = parentElement.find('.' + config.systemRouteModuleClass);
if(moduleElement.length > 0){
moduleElement.velocity('transition.slideDownOut', {

File diff suppressed because it is too large Load Diff

162
js/app/worker/map.js Normal file
View File

@@ -0,0 +1,162 @@
'use strict';
// "fake" window object will contain "MsgWorker" after import
let window = {}; // jshint ignore:line
// import "MsgWorker" class
self.importScripts( self.name ); // jshint ignore:line
let MsgWorker = window.MsgWorker;
let socket = null;
let ports = [];
let characterPorts = [];
// init "WebSocket" connection ========================================================================================
let initSocket = (uri) => {
let MsgWorkerOpen = new MsgWorker('ws:open');
if(socket === null){
socket = new WebSocket(uri);
// "WebSocket" open -----------------------------------------------------------------------
socket.onopen = (e) => {
MsgWorkerOpen.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerOpen);
};
// "WebSocket message ---------------------------------------------------------------------
socket.onmessage = (e) => {
let response = JSON.parse(e.data);
let MsgWorkerSend = new MsgWorker('ws:send');
MsgWorkerSend.task( response.task );
MsgWorkerSend.meta({
readyState: this.readyState,
characterIds: response.characterIds
});
MsgWorkerSend.data( response.load );
broadcastPorts(MsgWorkerSend);
};
// "WebSocket" close ----------------------------------------------------------------------
socket.onclose = (closeEvent) => {
let MsgWorkerClosed = new MsgWorker('ws:closed');
MsgWorkerClosed.meta({
readyState: socket.readyState,
code: closeEvent.code,
reason: closeEvent.reason,
wasClean: closeEvent.wasClean
});
broadcastPorts(MsgWorkerClosed);
socket = null; // reset WebSocket
};
// "WebSocket" error ----------------------------------------------------------------------
socket.onerror = (e) => {
let MsgWorkerError = new MsgWorker('ws:error');
MsgWorkerError.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerError);
};
}else{
// socket still open
MsgWorkerOpen.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerOpen);
}
};
// send message to port(s) ============================================================================================
let sendToCurrentPort = (load) => {
ports[ports.length - 1].postMessage(load);
};
let broadcastPorts = (load) => {
// default: sent to all ports
let sentToPorts = ports;
// check if send() is limited to some ports
let meta = load.meta();
if(
meta &&
meta.characterIds &&
meta.characterIds !== 'undefined' &&
meta.characterIds instanceof Array
){
// ... get ports for characterIds
sentToPorts = getPortsByCharacterIds(meta.characterIds);
}
for (let i = 0; i < sentToPorts.length; i++) {
sentToPorts[i].postMessage(load);
}
};
// port functions =====================================================================================================
let addPort = (port, characterId) => {
characterId = parseInt(characterId);
if(characterId > 0){
characterPorts.push({
characterId: characterId,
port: port
});
}else{
ports.push(port);
}
};
let getPortsByCharacterIds = (characterIds) => {
let ports = [];
for(let i = 0; i < characterPorts.length; i++){
for(let j = 0; j < characterIds.length; j++){
if(characterPorts[i].characterId === characterIds[j]){
ports.push(characterPorts[i].port);
}
}
}
return ports;
};
// "SharedWorker" connection ==========================================================================================
self.addEventListener('connect', (event) => { // jshint ignore:line
let port = event.ports[0];
addPort(port);
port.addEventListener('message', (e) => {
let MsgWorkerMessage = e.data;
Object.setPrototypeOf(MsgWorkerMessage, MsgWorker.prototype);
switch(MsgWorkerMessage.command){
case 'ws:init':
let data = MsgWorkerMessage.data();
// add character specific port (for broadcast) to individual ports (tabs)
addPort(port, data.characterId);
initSocket(data.uri);
break;
case 'ws:send':
let MsgSocket = {
task: MsgWorkerMessage.task(),
load: MsgWorkerMessage.data()
};
socket.send(JSON.stringify(MsgSocket));
break;
case 'ws:close':
// closeSocket();
break;
}
}, false);
port.start();
}, false);

55
js/app/worker/message.js Normal file
View File

@@ -0,0 +1,55 @@
window.MsgWorker = class MessageWorker {
constructor(cmd){
/**
* "command" type (identifies this message)
*/
this.cmd = cmd;
/**
* "task" what should be done with this message
* @type {string}
*/
this.msgTask = '';
/**
* "message" meta data (e.g. error/close data from WebSocket
* @type {null}
*/
this.msgMeta = null;
/**
* "message" body (load)
* @type {null}
*/
this.msgBody = null;
}
get command(){
return this.cmd;
}
task(task) {
if(task){
this.msgTask = task;
}
return this.msgTask;
}
meta(metaData) {
if(metaData){
this.msgMeta = metaData;
}
return this.msgMeta;
}
data(data) {
if(data){
this.msgBody = data;
}
return this.msgBody;
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -26,8 +26,8 @@ requirejs.config({
text: 'lib/requirejs/text', // v2.0.12 A RequireJS/AMD loader plugin for loading text resources.
mustache: 'lib/mustache.min', // v1.0.0 Javascript template engine - http://mustache.github.io
localForage: 'lib/localforage.min', // v1.4.2 localStorage library - https://mozilla.github.io/localForage
velocity: 'lib/velocity.min', // v1.2.2 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.0.4 plugin for velocity - http://julian.com/research/velocity/#uiPack
velocity: 'lib/velocity.min', // v1.4.1 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin http://plugins.adchsm.me/slidebars
jsPlumb: 'lib/dom.jsPlumb-1.7.6', // v1.7.6 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey

View File

@@ -5,7 +5,7 @@ define([
], function($, Init, Util) {
'use strict';
var config = {
let config = {
counterDigitSmallClass: 'pf-digit-counter-small',
counterDigitLargeClass: 'pf-digit-counter-large'
};
@@ -15,13 +15,13 @@ define([
* @param element
* @param tempDate
*/
var updateDateDiff = function(element, tempDate){
var diff = Util.getTimeDiffParts(tempDate, new Date());
var days = diff.days;
var hrs = diff.hours;
var min = diff.min;
var leftSec = diff.sec;
var value = [];
let updateDateDiff = function(element, tempDate){
let diff = Util.getTimeDiffParts(tempDate, new Date());
let days = diff.days;
let hrs = diff.hours;
let min = diff.min;
let leftSec = diff.sec;
let value = [];
if(
days > 0 ||
@@ -58,19 +58,22 @@ define([
*/
$.fn.initTimestampCounter = function(){
return this.each(function(){
var element = $(this);
var timestamp = parseInt( element.text() );
let element = $(this);
let timestamp = parseInt( element.text() );
// do not init twice
if(timestamp > 0){
// mark as init
element.attr('data-counter', 'init');
var date = new Date( timestamp * 1000);
let date = new Date( timestamp * 1000);
updateDateDiff(element, date);
var refreshIntervalId = window.setInterval(function(){
// show element (if invisible) after first update
element.css({'visibility': 'initial'});
let refreshIntervalId = window.setInterval(function(){
// update element with current time
if( !element.hasClass('stopCounter')){

View File

@@ -6,7 +6,7 @@ define(['jquery'], function($) {
'use strict';
var Config = {
let Config = {
path: {
img: 'public/img/', // path for images
// user API
@@ -22,6 +22,7 @@ define(['jquery'], function($) {
searchAccess: 'api/access/search', // ajax URL - search user/corporation/ally by name
// main config/map ping API
initMap: 'api/map/init', // ajax URL - get static data
getAccessData: 'api/map/getAccessData', // ajax URL - get map access tokens (WebSocket)
updateMapData: 'api/map/updateData', // ajax URL - main map update trigger
updateUserData: 'api/map/updateUserData', // ajax URL - main map user data trigger
// map API
@@ -63,11 +64,35 @@ define(['jquery'], function($) {
splashOverlay: 300, // "splash" loading overlay
headerLink: 100, // links in head bar
mapOverlay: 200, // show/hide duration for map overlays
mapMoveSystem: 300, // system position has changed animation
mapMoveSystem: 180, // system position has changed animation
mapDeleteSystem: 200, // remove system from map
mapModule: 200, // show/hide of an map module
dialogEvents: 180 // dialog events /slide/show/...
},
syncStatus: {
type: 'ajax',
webSocket: {
status: 'closed',
class: 'txt-color-danger',
timestamp: undefined
},
sharedWorker: {
status: 'offline', // SharedWorker status
class: 'txt-color-danger',
timestamp: undefined
},
ajax: {
status: 'enabled',
class: 'txt-color-success',
timestamp: undefined
}
},
performanceLogging: {
keyServerMapData: 'UPDATE_SERVER_MAP', // ajax request update map data
keyClientMapData: 'UPDATE_CLIENT_MAP', // update client map data
keyServerUserData: 'UPDATE_SERVER_USER_DATA', // ajax request update map user data
keyClientUserData: 'UPDATE_CLIENT_USER_DATA', // update client map user data
},
mapIcons: [ // map tab-icons
{
class: 'fa-desktop',

View File

@@ -11,288 +11,312 @@ define([
'use strict';
var logData = []; // cache object for all log entries
var logDataTable = null; // "Datatables" Object
let logData = []; // cache object for all log entries
let logDataTable = null; // "Datatables" Object
// Morris charts data
var maxGraphDataCount = 30; // max date entries for a graph
var chartData = {}; // chart Data object for all Morris Log graphs
let maxGraphDataCount = 30; // max date entries for a graph
let chartData = {}; // chart Data object for all Morris Log graphs
var config = {
dialogDynamicAreaClass: 'pf-dynamic-area', // class for dynamic areas
logGraphClass: 'pf-log-graph', // class for all log Morris graphs
tableToolsClass: 'pf-table-tools' // class for table tools
let config = {
taskDialogId: 'pf-task-dialog', // id for map "task manager" dialog
dialogDynamicAreaClass: 'pf-dynamic-area', // class for dynamic areas
timestampCounterClass: 'pf-timestamp-counter', // class for "timestamp" counter
taskDialogStatusAreaClass: 'pf-task-dialog-status', // class for "status" dynamic area
taskDialogLogTableAreaClass: 'pf-task-dialog-table', // class for "log table" dynamic area
logGraphClass: 'pf-log-graph', // class for all log Morris graphs
tableToolsClass: 'pf-table-tools' // class for table tools
};
/**
* get log time string
* @returns {string}
*/
var getLogTime = function(){
var serverTime = Util.getServerTime();
var logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
let getLogTime = function(){
let serverTime = Util.getServerTime();
let logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
return logTime;
};
/**
* updated "sync status" dynamic dialog area
*/
let updateSyncStatus = function(){
// check if task manager dialog is open
let logDialog = $('#' + config.taskDialogId);
if(logDialog.length){
// dialog is open
requirejs(['text!templates/modules/sync_status.html', 'mustache'], function(templateSyncStatus, Mustache) {
let data = {
timestampCounterClass: config.timestampCounterClass,
syncStatus: Init.syncStatus,
isWebSocket: () => {
return (Util.getSyncType() === 'webSocket');
},
isAjax: () => {
return (Util.getSyncType() === 'ajax');
}
};
let syncStatusElement = $( Mustache.render(templateSyncStatus, data ) );
logDialog.find('.' + config.taskDialogStatusAreaClass).html( syncStatusElement );
logDialog.find('.' + config.timestampCounterClass).initTimestampCounter();
syncStatusElement.initTooltips({
placement: 'right'
});
});
}
};
/**
* shows the logging dialog
*/
var showDialog = function(){
let showDialog = function(){
// dialog content
var content = $('<div>');
// content row for log graphs
var rowElementGraphs = $('<div>', {
class: 'row'
});
content.append(rowElementGraphs);
var tableHeadline = $('<h4>', {
text: ' Processes'
}).prepend( $('<i>', {
class: ['fa', 'fa-fw', 'fa-lg', 'fa-microchip'].join(' ')
}));
// add content Structure to dome before table initialization
content.append(tableHeadline);
// log table area --------------------------------------------------
var logTableArea = $('<div>', {
class: config.dialogDynamicAreaClass
});
var logTableActionBar = $('<div>', {
class: config.tableToolsClass
});
logTableArea.append(logTableActionBar);
var logTable = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
});
logTableArea.append(logTable);
content.append(logTableArea);
// init log table
logDataTable = logTable.DataTable({
paging: true,
ordering: true,
order: [ 1, 'desc' ],
autoWidth: false,
hover: false,
pageLength: 15,
lengthMenu: [[10, 15, 25, 50, 50], [10, 15, 25, 50, 50]],
data: logData, // load cached logs (if available)
language: {
emptyTable: 'No entries',
zeroRecords: 'No entries found',
lengthMenu: 'Show _MENU_ entries',
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
},
columnDefs: [
{
targets: 0,
title: '<i class="fa fa-lg fa-tag"></i>',
width: '18px',
searchable: false,
class: ['text-center'].join(' '),
data: 'status'
},{
targets: 1,
title: '<i class="fa fa-lg fa-fw fa-clock-o"></i>&nbsp;&nbsp;',
width: '50px',
searchable: true,
class: 'text-right',
data: 'time'
},{
targets: 2,
title: '<i class="fa fa-lg fa-fw fa-history"></i>&nbsp;&nbsp;',
width: '35px',
searchable: false,
class: 'text-right',
sType: 'html',
data: 'duration'
},{
targets: 3,
title: 'description',
searchable: true,
data: 'description'
},{
targets: 4,
title: 'type',
width: '40px',
searchable: true,
class: ['text-center'].join(' '),
data: 'type'
},{
targets: 5,
title: 'Prozess-ID&nbsp;&nbsp;&nbsp;',
width: '80px',
searchable: false,
class: 'text-right',
data: 'key'
}
]
});
// open dialog
var logDialog = bootbox.dialog({
title: 'Task-Manager',
message: content,
size: 'large',
buttons: {
close: {
label: 'close',
className: 'btn-default'
}
}
});
// modal dialog is shown
logDialog.on('shown.bs.modal', function(e) {
// show Morris graphs ----------------------------------------------------------
// function for chart label formation
var labelYFormat = function(y){
return Math.round(y) + 'ms';
requirejs(['text!templates/dialog/task_manager.html', 'mustache'], function(templateTaskManagerDialog, Mustache) {
let data = {
id: config.taskDialogId,
dialogDynamicAreaClass: config.dialogDynamicAreaClass,
taskDialogStatusAreaClass: config.taskDialogStatusAreaClass,
taskDialogLogTableAreaClass: config.taskDialogLogTableAreaClass,
tableActionBarClass: config.tableToolsClass
};
for(var key in chartData) {
if(chartData.hasOwnProperty(key)) {
// create a chart for each key
let contentTaskManager = $( Mustache.render(templateTaskManagerDialog, data) );
var colElementGraph = $('<div>', {
class: ['col-md-6'].join(' ')
});
let rowElementGraphs = contentTaskManager.find('.row');
let taskDialogLogTableAreaElement = contentTaskManager.find('.' + config.taskDialogLogTableAreaClass);
let logTable = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
});
// graph element
var graphElement = $('<div>', {
class: config.logGraphClass
});
taskDialogLogTableAreaElement.append(logTable);
var graphArea = $('<div>', {
class: config.dialogDynamicAreaClass
}).append( graphElement );
// headline
var headline = $('<h4>', {
text: key
}).prepend(
$('<span>', {
class: ['txt-color', 'txt-color-grayLight'].join(' '),
text: 'Prozess-ID: '
})
);
// show update ping between function calls
var updateElement = $('<small>', {
class: ['txt-color', 'txt-color-blue', 'pull-right'].join(' ')
});
headline.append(updateElement).append('<br>');
// show average execution time
var averageElement = $('<small>', {
class: 'pull-right'
});
headline.append(averageElement);
colElementGraph.append( headline );
colElementGraph.append( graphArea );
graphArea.showLoadingAnimation();
rowElementGraphs.append( colElementGraph );
// cache DOM Elements that will be updated frequently
chartData[key].averageElement = averageElement;
chartData[key].updateElement = updateElement;
chartData[key].graph = Morris.Area({
element: graphElement,
data: [],
xkey: 'x',
ykeys: ['y'],
labels: [key],
units: 'ms',
parseTime: false,
ymin: 0,
yLabelFormat: labelYFormat,
padding: 10,
hideHover: true,
pointSize: 3,
lineColors: ['#375959'],
pointFillColors: ['#477372'],
pointStrokeColors: ['#313335'],
lineWidth: 2,
grid: false,
gridStrokeWidth: 0.3,
gridTextSize: 9,
gridTextFamily: 'Oxygen Bold',
gridTextColor: '#63676a',
behaveLikeLine: true,
goals: [],
goalLineColors: ['#66c84f'],
smooth: false,
fillOpacity: 0.3,
resize: true
});
graphArea.hideLoadingAnimation();
}
}
// ------------------------------------------------------------------------------
// add dataTable buttons (extension)
var buttons = new $.fn.dataTable.Buttons( logDataTable, {
buttons: [
// init log table
logDataTable = logTable.DataTable({
paging: true,
ordering: true,
order: [ 1, 'desc' ],
autoWidth: false,
hover: false,
pageLength: 10,
lengthMenu: [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, 'All']],
data: logData, // load cached logs (if available)
language: {
emptyTable: 'No entries',
zeroRecords: 'No entries found',
lengthMenu: 'Show _MENU_ entries',
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
},
columnDefs: [
{
extend: 'copy',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-clipboard"></i> copy'
targets: 0,
title: '<i class="fa fa-lg fa-tag"></i>',
width: '18px',
searchable: false,
class: ['text-center'].join(' '),
data: 'status'
},{
extend: 'csv',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-download"></i> csv'
targets: 1,
title: '<i class="fa fa-lg fa-fw fa-clock-o"></i>&nbsp;&nbsp;',
width: '50px',
searchable: true,
class: 'text-right',
data: 'time'
},{
targets: 2,
title: '<i class="fa fa-lg fa-fw fa-history"></i>&nbsp;&nbsp;',
width: '35px',
searchable: false,
class: 'text-right',
sType: 'html',
data: 'duration'
},{
targets: 3,
title: 'description',
searchable: true,
data: 'description'
},{
targets: 4,
title: 'type',
width: '40px',
searchable: true,
class: ['text-center'].join(' '),
data: 'type'
},{
targets: 5,
title: 'Prozess-ID&nbsp;&nbsp;&nbsp;',
width: '80px',
searchable: false,
class: 'text-right',
data: 'key'
}
]
} );
logDataTable.buttons().container().appendTo( $(this).find('.' + config.tableToolsClass));
});
});
// modal dialog is closed
logDialog.on('hidden.bs.modal', function(e) {
// clear memory -> destroy all charts
for (var key in chartData) {
if (chartData.hasOwnProperty(key)) {
chartData[key].graph = null;
// open dialog
let logDialog = bootbox.dialog({
title: 'Task-Manager',
message: contentTaskManager,
size: 'large',
buttons: {
close: {
label: 'close',
className: 'btn-default'
}
}
}
});
});
// modal dialog before hide
logDialog.on('hide.bs.modal', function(e) {
// modal dialog is shown
logDialog.on('shown.bs.modal', function(e) {
updateSyncStatus();
// destroy logTable
logDataTable.destroy(true);
logDataTable= null;
// show Morris graphs ----------------------------------------------------------
// function for chart label formation
let labelYFormat = function(y){
return Math.round(y) + 'ms';
};
for(let key in chartData) {
if(chartData.hasOwnProperty(key)) {
// create a chart for each key
let colElementGraph = $('<div>', {
class: ['col-md-6'].join(' ')
});
// graph element
let graphElement = $('<div>', {
class: config.logGraphClass
});
let graphArea = $('<div>', {
class: config.dialogDynamicAreaClass
}).append( graphElement );
// headline
let headline = $('<h4>', {
text: key
}).prepend(
$('<span>', {
class: ['txt-color', 'txt-color-grayLight'].join(' '),
text: 'Prozess-ID: '
})
);
// show update ping between function calls
let updateElement = $('<small>', {
class: ['txt-color', 'txt-color-blue', 'pull-right'].join(' ')
});
headline.append(updateElement).append('<br>');
// show average execution time
let averageElement = $('<small>', {
class: 'pull-right'
});
headline.append(averageElement);
colElementGraph.append( headline );
colElementGraph.append( graphArea );
graphArea.showLoadingAnimation();
rowElementGraphs.append( colElementGraph );
// cache DOM Elements that will be updated frequently
chartData[key].averageElement = averageElement;
chartData[key].updateElement = updateElement;
chartData[key].graph = Morris.Area({
element: graphElement,
data: [],
xkey: 'x',
ykeys: ['y'],
labels: [key],
units: 'ms',
parseTime: false,
ymin: 0,
yLabelFormat: labelYFormat,
padding: 10,
hideHover: true,
pointSize: 3,
lineColors: ['#375959'],
pointFillColors: ['#477372'],
pointStrokeColors: ['#313335'],
lineWidth: 2,
grid: false,
gridStrokeWidth: 0.3,
gridTextSize: 9,
gridTextFamily: 'Oxygen Bold',
gridTextColor: '#63676a',
behaveLikeLine: true,
goals: [],
goalLineColors: ['#66c84f'],
smooth: false,
fillOpacity: 0.3,
resize: true
});
updateLogGraph(key);
graphArea.hideLoadingAnimation();
}
}
// ------------------------------------------------------------------------------
// add dataTable buttons (extension)
let buttons = new $.fn.dataTable.Buttons( logDataTable, {
buttons: [
{
extend: 'copy',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-clipboard"></i> copy'
},{
extend: 'csv',
className: 'btn btn-sm btn-default',
text: '<i class="fa fa-fw fa-download"></i> csv'
}
]
} );
logDataTable.buttons().container().appendTo( $(this).find('.' + config.tableToolsClass));
});
// modal dialog is closed
logDialog.on('hidden.bs.modal', function(e) {
// clear memory -> destroy all charts
for (let key in chartData) {
if (chartData.hasOwnProperty(key)) {
chartData[key].graph = null;
}
}
});
// modal dialog before hide
logDialog.on('hide.bs.modal', function(e) {
// destroy logTable
logDataTable.destroy(true);
logDataTable= null;
// remove event -> prevent calling this multiple times
$(this).off('hide.bs.modal');
});
// remove event -> prevent calling this multiple times
$(this).off('hide.bs.modal');
});
};
@@ -300,9 +324,9 @@ define([
/**
* updates the log graph for a log key
* @param key
* @param duration
* @param duration (if undefined -> just update graph with current data)
*/
var updateLogGraph = function(key, duration){
let updateLogGraph = function(key, duration){
// check if graph data already exist
if( !(chartData.hasOwnProperty(key))){
@@ -314,21 +338,23 @@ define([
}
// add new value
chartData[key].data.unshift(duration);
if(duration !== undefined){
chartData[key].data.unshift(duration);
}
if(chartData[key].data.length > maxGraphDataCount){
chartData[key].data = chartData[key].data.slice(0, maxGraphDataCount);
}
function getGraphData(data) {
var tempChartData = {
let tempChartData = {
data: [],
dataSum: 0,
average: 0
};
for(var x = 0; x < maxGraphDataCount; x++){
var value = 0;
for(let x = 0; x < maxGraphDataCount; x++){
let value = 0;
if(data[x]){
value = data[x];
tempChartData.dataSum = Number( (tempChartData.dataSum + value).toFixed(2) );
@@ -346,14 +372,14 @@ define([
return tempChartData;
}
var tempChartData = getGraphData(chartData[key].data);
let tempChartData = getGraphData(chartData[key].data);
// add new data to graph (Morris chart) - if is already initialized
if(chartData[key].graph !== null){
var avgElement = chartData[key].averageElement;
var updateElement = chartData[key].updateElement;
let avgElement = chartData[key].averageElement;
let updateElement = chartData[key].updateElement;
var delay = Util.getCurrentTriggerDelay( key, 0 );
let delay = Util.getCurrentTriggerDelay( key, 0 );
if(delay){
updateElement[0].textContent = ' delay: ' + delay + 'ms ';
@@ -365,8 +391,8 @@ define([
// change avg. display
avgElement[0].textContent = 'Avg. ' + tempChartData.average + 'ms';
var avgStatus = getLogStatusByDuration(key, tempChartData.average);
var avgStatusClass = Util.getLogInfo( avgStatus, 'class' );
let avgStatus = getLogStatusByDuration(key, tempChartData.average);
let avgStatusClass = Util.getLogInfo( avgStatus, 'class' );
//change avg. display class
if( !avgElement.hasClass(avgStatusClass) ){
@@ -376,7 +402,7 @@ define([
// change goals line color
if(avgStatus === 'warning'){
chartData[key].graph.options.goalLineColors = ['#e28a0d'];
$(document).setProgramStatus('problem');
$(document).setProgramStatus('slow connection');
}else{
chartData[key].graph.options.goalLineColors = ['#5cb85c'];
}
@@ -396,9 +422,8 @@ define([
* @param logDuration
* @returns {string}
*/
var getLogStatusByDuration = function(logKey, logDuration){
var logStatus = 'info';
let getLogStatusByDuration = function(logKey, logDuration){
let logStatus = 'info';
if( logDuration > Init.timer[logKey].EXECUTION_LIMIT ){
logStatus = 'warning';
}
@@ -410,9 +435,9 @@ define([
* @param logType
* @returns {string}
*/
var getLogTypeIconClass = function(logType){
let getLogTypeIconClass = function(logType){
var logIconClass = '';
let logIconClass = '';
switch(logType){
case 'client':
@@ -427,11 +452,15 @@ define([
};
/**
* init logging -> set global log event
* init logging -> set global log events
*/
var init = function(){
let init = function(){
var maxEntries = 150;
let maxEntries = 150;
$(window).on('pf:syncStatus', function(){
updateSyncStatus();
});
// set global logging listener
$(window).on('pf:log', function(e, logKey, options){
@@ -442,21 +471,19 @@ define([
options.duration &&
options.description
){
var logDescription = options.description;
var logDuration = options.duration;
var logType = options.type;
let logDescription = options.description;
let logDuration = options.duration;
let logType = options.type;
// check log status by duration
var logStatus = getLogStatusByDuration(logKey, logDuration);
var statusClass = Util.getLogInfo( logStatus, 'class' );
var typeIconClass = getLogTypeIconClass(logType);
let logStatus = getLogStatusByDuration(logKey, logDuration);
let statusClass = Util.getLogInfo( logStatus, 'class' );
let typeIconClass = getLogTypeIconClass(logType);
// update graph data
updateLogGraph(logKey, logDuration);
var logRowData = {
let logRowData = {
status: '<i class="fa fa-fw fa-circle txt-color ' + statusClass + '"></i>',
time: getLogTime(),
duration: '<span class="txt-color ' + statusClass + '">' + logDuration + '<small>ms</small></span>',
@@ -476,7 +503,7 @@ define([
}
// delete old log entries from table ---------------------------------
var rowCount = logData.length;
let rowCount = logData.length;
if( rowCount >= maxEntries ){

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ define([
'use strict';
var config = {
let config = {
logTimerCount: 3, // map log timer in seconds
// map
@@ -29,6 +29,16 @@ define([
connectionOverlayEolId: 'overlayEol' // connection overlay ID (jsPlumb)
};
/**
* get mapElement from overlay or any child of that
* @param mapOverlay
* @returns {JQuery}
*/
let getMapFromOverlay = function(mapOverlay){
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
/**
* Overlay options (all available map options shown in overlay)
* "active": (active || hover) indicated whether an icon/option
@@ -36,7 +46,7 @@ define([
* "active": Makes icon active when visible
* "hover": Make icon active on hover
*/
var options = {
let options = {
filter: {
title: 'active filter',
trigger: 'active',
@@ -62,9 +72,9 @@ define([
iconClass: ['fa', 'fa-fw', 'fa-tags'],
hoverIntent: {
over: function(e){
var mapElement = getMapFromOverlay(this);
let mapElement = getMapFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).each(function(){
var system = $(this);
let system = $(this);
// init tooltip if not already exists
if ( !system.data('bs.tooltip') ){
system.tooltip({
@@ -80,7 +90,7 @@ define([
});
},
out: function(e){
var mapElement = getMapFromOverlay(this);
let mapElement = getMapFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).tooltip('hide');
}
}
@@ -92,20 +102,20 @@ define([
iconClass: ['fa', 'fa-fw', 'fa-clock-o'],
hoverIntent: {
over: function(e){
var mapElement = getMapFromOverlay(this);
var MapUtil = require('app/map/util');
var Map = require('app/map/map');
var map = Map.getMapInstance( mapElement.data('id') );
var connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
var serverDate = Util.getServerTime();
let mapElement = getMapFromOverlay(this);
let MapUtil = require('app/map/util');
let Map = require('app/map/map');
let map = Map.getMapInstance( mapElement.data('id') );
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let serverDate = Util.getServerTime();
for (let connection of connections) {
var eolTimestamp = connection.getParameter('eolUpdated');
var eolDate = Util.convertTimestampToServerTime(eolTimestamp);
var diff = Util.getTimeDiffParts(eolDate, serverDate);
let eolTimestamp = connection.getParameter('eolUpdated');
let eolDate = Util.convertTimestampToServerTime(eolTimestamp);
let diff = Util.getTimeDiffParts(eolDate, serverDate);
// format overlay label
var label = '';
let label = '';
if(diff.days){
label += diff.days + 'd ';
}
@@ -124,11 +134,11 @@ define([
}
},
out: function(e){
var mapElement = getMapFromOverlay(this);
var MapUtil = require('app/map/util');
var Map = require('app/map/map');
var map = Map.getMapInstance( mapElement.data('id') );
var connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let mapElement = getMapFromOverlay(this);
let MapUtil = require('app/map/util');
let Map = require('app/map/map');
let map = Map.getMapInstance( mapElement.data('id') );
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
for (let connection of connections) {
connection.removeOverlay(config.connectionOverlayEolId);
@@ -138,15 +148,6 @@ define([
}
};
/**
* get mapElement from overlay or any child of that
* @param mapOverlay
* @returns {JQuery}
*/
var getMapFromOverlay = function(mapOverlay){
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
/**
* get map overlay element by type e.g. timer/counter, info - overlay
* @param overlayType
@@ -154,9 +155,9 @@ define([
*/
$.fn.getMapOverlay = function(overlayType){
var mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
let mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
var mapOverlay = null;
let mapOverlay = null;
switch(overlayType){
case 'timer':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
@@ -172,14 +173,15 @@ define([
/**
* draws the map update counter to the map overlay timer
* @param percent
* @param value
* @returns {*}
*/
$.fn.setMapUpdateCounter = function(percent, value){
var mapOverlayTimer = $(this);
let mapOverlayTimer = $(this);
// check if counter already exists
var counterChart = mapOverlayTimer.getMapCounter();
let counterChart = mapOverlayTimer.getMapCounter();
if(counterChart.length === 0){
// create new counter
@@ -212,7 +214,7 @@ define([
*/
$.fn.getMapCounter = function(){
var mapOverlayTimer = $(this);
let mapOverlayTimer = $(this);
return mapOverlayTimer.find('.' + Init.classes.pieChart.pieChartMapCounterClass);
};
@@ -222,18 +224,18 @@ define([
*/
$.fn.startMapUpdateCounter = function(){
var mapOverlayTimer = $(this);
var counterChart = mapOverlayTimer.getMapCounter();
let mapOverlayTimer = $(this);
let counterChart = mapOverlayTimer.getMapCounter();
var maxSeconds = config.logTimerCount;
let maxSeconds = config.logTimerCount;
var counterChartLabel = counterChart.find('span');
let counterChartLabel = counterChart.find('span');
var percentPerCount = 100 / maxSeconds;
let percentPerCount = 100 / maxSeconds;
// update counter
var updateChart = function(tempSeconds){
var pieChart = counterChart.data('easyPieChart');
let updateChart = function(tempSeconds){
let pieChart = counterChart.data('easyPieChart');
if(pieChart !== undefined){
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
@@ -242,13 +244,12 @@ define([
};
// main timer function is called on any counter update
var timer = function(){
let timer = function(mapUpdateCounter){
// decrease timer
var currentSeconds = counterChart.data('currentSeconds');
let currentSeconds = counterChart.data('currentSeconds');
currentSeconds--;
counterChart.data('currentSeconds', currentSeconds);
if(currentSeconds >= 0){
// update counter
updateChart(currentSeconds);
@@ -266,7 +267,7 @@ define([
};
// get current seconds (in case the timer is already running)
var currentSeconds = counterChart.data('currentSeconds');
let currentSeconds = counterChart.data('currentSeconds');
// start values for timer and chart
counterChart.data('currentSeconds', maxSeconds);
@@ -277,7 +278,9 @@ define([
currentSeconds < 0
){
// start timer
var mapUpdateCounter = setInterval(timer, 1000);
let mapUpdateCounter = setInterval(() => {
timer(mapUpdateCounter);
}, 1000);
// store counter interval
counterChart.data('interval', mapUpdateCounter);
@@ -296,14 +299,14 @@ define([
* @param viewType
*/
$.fn.updateOverlayIcon = function(option, viewType){
var mapOverlayInfo = $(this);
let mapOverlayInfo = $(this);
var showOverlay = false;
let showOverlay = false;
var mapOverlayIconClass = options[option].class;
let mapOverlayIconClass = options[option].class;
// look for the overlay icon that should be updated
var iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
let iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
if(iconElement){
if(viewType === 'show'){
@@ -335,7 +338,7 @@ define([
iconElement.data('visible', false);
// check if there is any visible icon remaining
var visibleIcons = mapOverlayInfo.find('i:visible');
let visibleIcons = mapOverlayInfo.find('i:visible');
if(visibleIcons.length > 0){
showOverlay = true;
}
@@ -364,23 +367,23 @@ define([
*/
$.fn.initMapOverlays = function(){
return this.each(function(){
var parentElement = $(this);
let parentElement = $(this);
var mapOverlayTimer = $('<div>', {
let mapOverlayTimer = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayTimerClass].join(' ')
});
parentElement.append(mapOverlayTimer);
// ---------------------------------------------------------------------------
// add map overlay info. after scrollbar is initialized
var mapOverlayInfo = $('<div>', {
let mapOverlayInfo = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayInfoClass].join(' ')
});
// add all overlay elements
for (var prop in options) {
for (let prop in options) {
if(options.hasOwnProperty(prop)){
var icon = $('<i>', {
let icon = $('<i>', {
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
}).attr('title', options[prop].title).tooltip({
placement: 'bottom',

View File

@@ -12,7 +12,7 @@ define([
], ($, Init, Util, bootbox, MapUtil) => {
'use strict';
var config = {
let config = {
systemActiveClass: 'pf-system-active' // class for an active system in a map
};
@@ -22,13 +22,13 @@ define([
*/
$.fn.showRallyPointDialog = (system) => {
requirejs(['text!templates/dialog/system_rally.html', 'mustache'], function(template, Mustache) {
var data = {
let data = {
notificationStatus: Init.notificationStatus.rallySet
};
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var rallyDialog = bootbox.dialog({
let rallyDialog = bootbox.dialog({
message: content,
title: 'Set rally point for "' + system.getSystemInfo( ['alias'] ) + '"',
buttons: {
@@ -66,9 +66,9 @@ define([
* @returns {*}
*/
$.fn.showDeleteSystemDialog = (map, systems = []) => {
var mapContainer = $( map.getContainer() );
var validDeleteSystems = [];
var activeCharacters = 0;
let mapContainer = $( map.getContainer() );
let validDeleteSystems = [];
let activeCharacters = 0;
// check if systems belong to map -> security check
for (let system of systems) {
let systemElement = $(system);
@@ -84,13 +84,13 @@ define([
}
if(validDeleteSystems.length){
var msg = '';
let msg = '';
if(validDeleteSystems.length === 1){
var deleteSystem = $(validDeleteSystems[0]);
var systemName = deleteSystem.data('name');
var systemAlias = deleteSystem.getSystemInfo( ['alias'] );
let deleteSystem = $(validDeleteSystems[0]);
let systemName = deleteSystem.data('name');
let systemAlias = deleteSystem.getSystemInfo( ['alias'] );
var systemNameStr = (systemName === systemAlias) ? '"' + systemName + '"' : '"' + systemAlias + '" (' + systemName + ')';
let systemNameStr = (systemName === systemAlias) ? '"' + systemName + '"' : '"' + systemAlias + '" (' + systemName + ')';
systemNameStr = '<span class="txt-color txt-color-warning">' + systemNameStr + '</span>';
msg = 'Delete system ' + systemNameStr + ' and all its connections?';
}else{
@@ -102,7 +102,7 @@ define([
msg += ' <span class="txt-color txt-color-warning">Warning: ' + activeCharacters + ' active characters</span>';
}
var systemDeleteDialog = bootbox.confirm(msg, result => {
let systemDeleteDialog = bootbox.confirm(msg, result => {
if(result){
deleteSystems(map, validDeleteSystems, (systems) => {
// callback function after deleted -> close dialog
@@ -130,14 +130,14 @@ define([
* @param systems
* @param callback function
*/
var deleteSystems = (map, systems = [], callback = (systems) => {}) => {
var mapContainer = $( map.getContainer() );
mapContainer.getMapOverlay('timer').startMapUpdateCounter();
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
let mapContainer = $( map.getContainer() );
$.ajax({
type: 'POST',
url: Init.path.deleteSystem,
data: {
mapId: mapContainer.data('id'),
systemIds: systems.map( system => $(system).data('id') )
},
dataType: 'json',
@@ -151,7 +151,7 @@ define([
callback(this.systems);
}).fail(function(jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
});
@@ -162,9 +162,9 @@ define([
* @param map
* @param systems
*/
var removeSystems = (map, systems) => {
let removeSystems = (map, systems) => {
var removeSystemCallbak = function(deleteSystem){
let removeSystemCallbak = function(deleteSystem){
map.remove(deleteSystem);
};
@@ -174,7 +174,7 @@ define([
// check if system is "active"
if( system.hasClass(config.systemActiveClass) ){
// get parent Tab Content and fire clear modules event
var tabContentElement = MapUtil.getTabContentElementByMapElement( system );
let tabContentElement = MapUtil.getTabContentElementByMapElement( system );
$(tabContentElement).trigger('pf:removeSystemModules');
}

View File

@@ -9,7 +9,7 @@ define([
], function($, Init, Util) {
'use strict';
var config = {
let config = {
mapSnapToGridDimension: 20, // px for grid snapping (grid YxY)
// local storage
@@ -22,7 +22,7 @@ define([
};
// map menu options
var mapOptions = {
let mapOptions = {
mapMagnetizer: {
buttonId: Util.config.menuButtonMagnetizerId,
description: 'Magnetizer',
@@ -42,23 +42,23 @@ define([
* @param {bool} filterByUser
* @returns {Array}
*/
var getMapTypes = function(filterByUser){
var mapTypes = [];
let getMapTypes = function(filterByUser){
let mapTypes = [];
$.each(Init.mapTypes, function(prop, data){
// skip "default" type -> just for 'add' icon
if(data.label.length > 0){
var tempData = data;
let tempData = data;
tempData.name = prop;
mapTypes.push(tempData);
}
});
if(filterByUser === true){
var corporationId = Util.getCurrentUserInfo('corporationId');
var allianceId = Util.getCurrentUserInfo('allianceId');
let corporationId = Util.getCurrentUserInfo('corporationId');
let allianceId = Util.getCurrentUserInfo('allianceId');
var authorizedMapTypes = [];
let authorizedMapTypes = [];
// check if character data exists
if(corporationId > 0) {
authorizedMapTypes.push('corporation');
@@ -71,9 +71,9 @@ define([
authorizedMapTypes.push('private');
// compare "all" map types with "authorized" types
var tempMapTypes = [];
for(var i = 0; i < mapTypes.length; i++){
for(var j = 0; j < authorizedMapTypes.length; j++){
let tempMapTypes = [];
for(let i = 0; i < mapTypes.length; i++){
for(let j = 0; j < authorizedMapTypes.length; j++){
if(mapTypes[i].name === authorizedMapTypes[j]){
tempMapTypes.push(mapTypes[i]);
break;
@@ -91,10 +91,10 @@ define([
* get all available scopes for a map
* @returns {Array}
*/
var getMapScopes = function(){
var scopes = [];
let getMapScopes = function(){
let scopes = [];
$.each(Init.mapScopes, function(prop, data){
var tempData = data;
let tempData = data;
tempData.name = prop;
scopes.push(tempData);
});
@@ -108,8 +108,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getScopeInfoForMap = function(info, option){
var scopeInfo = '';
let getScopeInfoForMap = function(info, option){
let scopeInfo = '';
if(Init.mapScopes.hasOwnProperty(info)){
scopeInfo = Init.mapScopes[info][option];
}
@@ -120,7 +120,7 @@ define([
* get all available map icons
* @returns {Object[]}
*/
var getMapIcons = function(){
let getMapIcons = function(){
return Init.mapIcons;
};
@@ -130,8 +130,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getInfoForMap = function(mapType, option){
var mapInfo = '';
let getInfoForMap = function(mapType, option){
let mapInfo = '';
if(Init.mapTypes.hasOwnProperty(mapType)){
mapInfo = Init.mapTypes[mapType][option];
}
@@ -144,8 +144,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getInfoForSystem = function(info, option){
var systemInfo = '';
let getInfoForSystem = function(info, option){
let systemInfo = '';
if(Init.classes.systemInfo.hasOwnProperty(info)){
systemInfo = Init.classes.systemInfo[info][option];
}
@@ -158,8 +158,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getSystemTypeInfo = function(systemTypeId, option){
var systemTypeInfo = '';
let getSystemTypeInfo = function(systemTypeId, option){
let systemTypeInfo = '';
$.each(Init.systemType, function(prop, data){
if(systemTypeId === data.id){
systemTypeInfo = data[option];
@@ -175,8 +175,8 @@ define([
* @param option
* @returns {string}
*/
var getEffectInfoForSystem = function(effect, option){
var effectInfo = '';
let getEffectInfoForSystem = function(effect, option){
let effectInfo = '';
if( Init.classes.systemEffects.hasOwnProperty(effect) ){
effectInfo = Init.classes.systemEffects[effect][option];
}
@@ -198,9 +198,9 @@ define([
* @param {JQuery[]} systems - system DOM elements
* @returns {Array} connections - found connection, DOM elements
*/
var searchConnectionsBySystems = function(map, systems){
var connections = [];
var withBackConnection = false;
let searchConnectionsBySystems = function(map, systems){
let connections = [];
let withBackConnection = false;
$.each(systems, function(i, system){
// get connections where system is source
@@ -221,15 +221,15 @@ define([
* @param {string|string[]} type
* @returns {Array}
*/
var searchConnectionsByScopeAndType = function(map, scope, type){
var connections = [];
var scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
var typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
let searchConnectionsByScopeAndType = function(map, scope, type){
let connections = [];
let scopeArray = (scope === undefined) ? ['*'] : ((Array.isArray(scope)) ? scope : [scope]);
let typeArray = (type === undefined) ? [] : ((Array.isArray(type)) ? type : [type]);
map.select({scope: scopeArray}).each(function(connection){
if(typeArray.length > 0){
// filter by connection type as well...
for(var i = 0; i < typeArray.length; i++){
for(let i = 0; i < typeArray.length; i++){
if( connection.hasType(typeArray[i]) ){
connections.push(connection);
break; // don´t add same connection multiple times
@@ -250,8 +250,8 @@ define([
* @param {string} option
* @returns {string}
*/
var getConnectionInfo = function(connectionTyp, option){
var connectionInfo = '';
let getConnectionInfo = function(connectionTyp, option){
let connectionInfo = '';
if(Init.connectionTypes.hasOwnProperty(connectionTyp)){
connectionInfo = Init.connectionTypes[connectionTyp][option];
}
@@ -265,8 +265,8 @@ define([
* @param {JQuery} systemB
* @returns {Array}
*/
var checkForConnection = function(map, systemA, systemB){
var connections = [];
let checkForConnection = function(map, systemA, systemB){
let 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}) );
@@ -279,8 +279,8 @@ define([
* @param {string} scope
* @returns {string}
*/
var getDefaultConnectionTypeByScope = function(scope){
var type = '';
let getDefaultConnectionTypeByScope = function(scope){
let type = '';
switch(scope){
case 'wh':
type = 'wh_fresh';
@@ -303,7 +303,7 @@ define([
* @param {Object} connection - jsPlumb object
* @param {string} status
*/
var setConnectionWHStatus = function(connection, status){
let setConnectionWHStatus = function(connection, status){
if(
status === 'wh_fresh' &&
connection.hasType('wh_fresh') !== true
@@ -344,13 +344,13 @@ define([
* @param {string} option
* @returns {string}
*/
var getScopeInfoForConnection = function(info, option){
var scopeInfo = '';
let getScopeInfoForConnection = function(info, option){
let scopeInfo = '';
if(Init.connectionScopes.hasOwnProperty(info)){
switch(option){
case 'connectorDefinition':
// json data in DB
var temp = '{ "data": ' + Init.connectionScopes[info][option] + '}';
let temp = '{ "data": ' + Init.connectionScopes[info][option] + '}';
scopeInfo = $.parseJSON( temp).data;
break;
default:
@@ -367,11 +367,114 @@ define([
* @param element
* @returns {*}
*/
var getTabContentElementByMapElement = function(element){
var tabContentElement = $(element).parents('.' + config.mapTabContentClass);
let getTabContentElementByMapElement = function(element){
let tabContentElement = $(element).parents('.' + config.mapTabContentClass);
return tabContentElement;
};
/**
* store mapId for current user (IndexedDB)
* @param mapId
*/
let storeDefaultMapId = function(mapId){
if(mapId > 0){
let userData = Util.getCurrentUserData();
if(
userData &&
userData.character
){
storeLocalData('character', userData.character.id, 'defaultMapId', mapId);
}
}
};
/**
* get key prefix for local storage data
* @param type
* @returns {boolean}
*/
let getLocalStoragePrefixByType = function(type){
let prefix = false;
switch(type){
case 'character': prefix = config.characterLocalStoragePrefix; break;
case 'map': prefix = config.mapLocalStoragePrefix; break;
default: prefix = config.mapLocalStoragePrefix;
}
return prefix;
};
/**
* get stored local data from client cache (IndexedDB)
* @param type
* @param objectId
* @returns {*}
*/
let getLocaleData = function(type, objectId){
if(objectId > 0){
let storageKey = getLocalStoragePrefixByType(type) + objectId;
return Util.getLocalStorage().getItem(storageKey);
}else{
console.warn('Local storage requires object id > 0');
}
};
/**
* store local config data to client cache (IndexedDB)
* @param type
* @param objectId
* @param key
* @param value
*/
let storeLocalData = function(type, objectId, key, value){
if(objectId > 0){
// get current map config
let storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
data = (data === null) ? {} : data;
// set/update value
data[this.key] = this.value;
Util.getLocalStorage().setItem(this.storageKey, data);
}.bind({
key: key,
value: value,
storageKey: storageKey
})).catch(function(err) {
// This code runs if there were any errors
console.error('Map local storage can not be accessed!');
});
}else{
console.warn('storeLocalData(): Local storage requires object id > 0');
}
};
/**
* delete local map configuration by key (IndexedDB)
* @param type
* @param objectId
* @param key
*/
let deleteLocalData = function(type, objectId, key){
if(objectId > 0){
// get current map config
let storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
if(
data &&
data.hasOwnProperty(key)
){
delete data[key];
Util.getLocalStorage().setItem(this.storageKey, data);
}
}.bind({
storageKey: storageKey
}));
}else{
console.warn('deleteLocalData(): Local storage requires object id > 0');
}
};
/**
* set or change rallyPoint for systems
* @param rallyUpdated
@@ -380,9 +483,9 @@ define([
*/
$.fn.setSystemRally = function(rallyUpdated, options){
rallyUpdated = rallyUpdated || 0;
var rallyPoke = false;
let rallyPoke = false;
var defaultOptions = {
let defaultOptions = {
poke: false,
hideNotification: false,
hideCounter: false,
@@ -390,8 +493,8 @@ define([
options = $.extend({}, defaultOptions, options);
return this.each(function(){
var system = $(this);
var rally = system.data('rallyUpdated') || 0;
let system = $(this);
let rally = system.data('rallyUpdated') || 0;
if(rallyUpdated !== rally){
// rally status changed
@@ -399,7 +502,7 @@ define([
system.getMapOverlay('timer').startMapUpdateCounter();
}
var rallyClass = getInfoForSystem('rally', 'class');
let rallyClass = getInfoForSystem('rally', 'class');
if(rallyUpdated > 0){
// new rally point set OR update system with rally information
@@ -408,7 +511,7 @@ define([
// rallyUpdated > 0 is required for poke!
rallyPoke = options.poke;
var notificationOptions = {
let notificationOptions = {
title: 'Rally Point',
text: 'System: ' + system.data('name')
};
@@ -421,13 +524,13 @@ define([
// rally saved AND poke option active
// check if desktop notification was already send
var mapId = system.data('mapid');
var systemId = system.data('id');
var promiseStore = getLocaleData('map', mapId);
let mapId = system.data('mapid');
let systemId = system.data('id');
let promiseStore = getLocaleData('map', mapId);
promiseStore.then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
var rallyPokeData = {};
let rallyPokeData = {};
if(
data &&
@@ -468,109 +571,6 @@ define([
});
};
/**
* store mapId for current user (IndexedDB)
* @param mapId
*/
var storeDefaultMapId = function(mapId){
if(mapId > 0){
var userData = Util.getCurrentUserData();
if(
userData &&
userData.character
){
storeLocalData('character', userData.character.id, 'defaultMapId', mapId);
}
}
};
/**
* get key prefix for local storage data
* @param type
* @returns {boolean}
*/
var getLocalStoragePrefixByType = function(type){
var prefix = false;
switch(type){
case 'character': prefix = config.characterLocalStoragePrefix; break;
case 'map': prefix = config.mapLocalStoragePrefix; break;
default: prefix = config.mapLocalStoragePrefix;
}
return prefix;
};
/**
* get stored local data from client cache (IndexedDB)
* @param type
* @param objectId
* @returns {*}
*/
var getLocaleData = function(type, objectId){
if(objectId > 0){
var storageKey = getLocalStoragePrefixByType(type) + objectId;
return Util.getLocalStorage().getItem(storageKey);
}else{
console.warn('Local storage requires object id > 0');
}
};
/**
* store local config data to client cache (IndexedDB)
* @param type
* @param objectId
* @param key
* @param value
*/
var storeLocalData = function(type, objectId, key, value){
if(objectId > 0){
// get current map config
var storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
// This code runs once the value has been loaded
// from the offline store.
data = (data === null) ? {} : data;
// set/update value
data[this.key] = this.value;
Util.getLocalStorage().setItem(this.storageKey, data);
}.bind({
key: key,
value: value,
storageKey: storageKey
})).catch(function(err) {
// This code runs if there were any errors
console.error('Map local storage can not be accessed!');
});
}else{
console.warn('storeLocalData(): Local storage requires object id > 0');
}
};
/**
* delete local map configuration by key (IndexedDB)
* @param type
* @param objectId
* @param key
*/
var deleteLocalData = function(type, objectId, key){
if(objectId > 0){
// get current map config
var storageKey = getLocalStoragePrefixByType(type) + objectId;
Util.getLocalStorage().getItem(storageKey).then(function(data) {
if(
data &&
data.hasOwnProperty(key)
){
delete data[key];
Util.getLocalStorage().setItem(this.storageKey, data);
}
}.bind({
storageKey: storageKey
}));
}else{
console.warn('deleteLocalData(): Local storage requires object id > 0');
}
};
return {
config: config,
mapOptions: mapOptions,

View File

@@ -0,0 +1,126 @@
/**
* SharedWorker config for map
*/
define([
'app/util'
], function(Util) {
'use strict';
let config = {
};
let sharedWorker = null;
let MsgWorker = null;
let characterId = null;
/**
* get WebSocket URL for SharedWorker script
* @returns {string}
*/
let getWebSocketURL = () => {
let domain = location.host;
let workerProtocol = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
return workerProtocol + '//' + domain + '/ws/map/update';
};
/**
* get SharedWorker Script path
* @returns {string}
*/
let getWorkerScript = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/map.js';
};
/**
* get path to message object
* @returns {string}
*/
let getMessageWorkerObjectPath = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/message.js';
};
/**
* init (connect) WebSocket within SharedWorker
*/
let initSocket = () => {
let MsgWorkerInit = new MsgWorker('ws:init');
MsgWorkerInit.data({
uri: getWebSocketURL(),
characterId: characterId,
});
sharedWorker.port.postMessage(MsgWorkerInit);
};
/**
* init (start/connect) to "SharedWorker"
* -> set worker events
*/
let init = (config) => {
// set characterId that is connected with this SharedWorker PORT
characterId = parseInt(config.characterId);
// get message Class for App <=> SharedWorker MessageEvent communication
requirejs([getMessageWorkerObjectPath()], () => {
MsgWorker = window.MsgWorker;
// start/connect to "SharedWorker"
sharedWorker = new SharedWorker( getWorkerScript(), getMessageWorkerObjectPath() );
sharedWorker.port.addEventListener('message', (e) => {
let MsgWorkerMessage = e.data;
Object.setPrototypeOf(MsgWorkerMessage, MsgWorker.prototype);
switch(MsgWorkerMessage.command){
case 'ws:open':
config.callbacks.onOpen(MsgWorkerMessage);
break;
case 'ws:send':
config.callbacks.onGet(MsgWorkerMessage);
break;
case 'ws:closed':
config.callbacks.onClosed(MsgWorkerMessage);
break;
case 'ws:error':
config.callbacks.onError(MsgWorkerMessage);
break;
}
}, false);
sharedWorker.onerror = (e) => {
// could not connect to SharedWorker script -> send error back
let MsgWorkerError = new MsgWorker('sw:error');
MsgWorkerError.meta({
reason: 'Could not connect to SharedWorker: ' + getWorkerScript()
});
config.callbacks.onError(MsgWorkerError);
};
sharedWorker.port.start();
// SharedWorker initialized
let MsgWorkerInit = new MsgWorker('sw:init');
config.callbacks.onInit(MsgWorkerInit);
// startWebSocket
initSocket();
});
};
let send = (task, data) => {
let MsgWorkerSend = new MsgWorker('ws:send');
MsgWorkerSend.task(task);
MsgWorkerSend.data(data);
sharedWorker.port.postMessage(MsgWorkerSend);
};
return {
init: init,
send: send
};
});

View File

@@ -9,16 +9,17 @@ define([
'app/render',
'app/logging',
'app/page',
'app/map/worker',
'app/ui/form_element',
'app/module_map'
], function($, Init, Util, Render, Logging, Page) {
], ($, Init, Util, Render, Logging, Page, MapWorker) => {
'use strict';
/**
* main init "map" page
*/
$(function(){
$(() => {
Util.initPrototypes();
// set default AJAX config
@@ -36,14 +37,14 @@ define([
// init logging
Logging.init();
var mapModule = $('#' + Util.config.mapModuleId);
let mapModule = $('#' + Util.config.mapModuleId);
// map init load static data =======================================================
$.getJSON( Init.path.initMap, function( initData ) {
$.getJSON( Init.path.initMap, (initData) => {
if( initData.error.length > 0 ){
for(var i = 0; i < initData.error.length; i++){
for(let i = 0; i < initData.error.length; i++){
Util.showNotify({
title: initData.error[i].title,
text: initData.error[i].message,
@@ -69,207 +70,77 @@ define([
// init map module
mapModule.initMapModule();
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + jqXHR.status + ': ' + error;
}).fail(( jqXHR, status, error) => {
let reason = status + ' ' + jqXHR.status + ': ' + error;
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
});
/**
* request all map access data (tokens) -> required wor WebSocket subscription
*/
let getMapAccessData = () => {
$.getJSON( Init.path.getAccessData, ( response ) => {
if(response.status === 'OK'){
// init SharedWorker for maps
MapWorker.init({
characterId: response.data.id,
callbacks: {
onInit: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command);
},
onOpen: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
MapWorker.send( 'subscribe', response.data);
},
onGet: (MsgWorkerMessage) => {
switch(MsgWorkerMessage.task()){
case 'mapUpdate':
Util.updateCurrentMapData( MsgWorkerMessage.data() );
mapModule.updateMapModule();
break;
case 'mapAccess':
case 'mapDeleted':
Util.deleteCurrentMapData( MsgWorkerMessage.data() );
mapModule.updateMapModule();
break;
}
Util.setSyncStatus('ws:get');
},
onClosed: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
},
onError: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
}
}
});
}
});
};
getMapAccessData();
/**
* main function for init all map relevant trigger calls
*/
$.fn.initMapModule = function(){
var mapModule = $(this);
let mapModule = $(this);
// log keys ------------------------------------------------------------------------
// ajax request update map data
var logKeyServerMapData = 'UPDATE_SERVER_MAP';
// update client map data
var logKeyClientMapData = 'UPDATE_CLIENT_MAP';
// ajax request update map user data
var logKeyServerUserData = 'UPDATE_SERVER_USER_DATA';
// update client map user data
var logKeyClientUserData = 'UPDATE_CLIENT_USER_DATA';
let logKeyServerMapData = Init.performanceLogging.keyServerMapData;
let logKeyServerUserData = Init.performanceLogging.keyServerUserData;
// main update intervals/trigger (heartbeat)
var updateTimeouts = {
let updateTimeouts = {
mapUpdate: 0,
userUpdate: 0
};
var locationToggle = $('#' + Util.config.headMapTrackingId);
// ping for main map update ========================================================
var triggerMapUpdatePing = function(){
// check each execution time if map module is still available
var check = $('#' + mapModule.attr('id')).length;
if(check === 0){
// program crash stop any update
return;
}
// get updated map data
var updatedMapData = {
mapData: mapModule.getMapModuleDataForUpdate(),
getUserData: ( Util.getCurrentUserData() ) ? 0 : 1
};
// start log
Util.timeStart(logKeyServerMapData);
// store updatedMapData
$.ajax({
type: 'POST',
url: Init.path.updateMapData,
data: updatedMapData,
dataType: 'json'
}).done(function(data){
// log request time
var duration = Util.timeStop(logKeyServerMapData);
Util.log(logKeyServerMapData, {duration: duration, type: 'server', description: 'request map data'});
if(
data.error &&
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined) {
// store current user data global (cache)
Util.setCurrentUserData(data.userData);
}
if(data.mapData.length === 0){
// clear all existing maps
mapModule.clearMapModule();
// no map data available -> show "new map" dialog
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
}else{
// map data found
// start log
Util.timeStart(logKeyClientMapData);
// load/update main map module
mapModule.updateMapModule(data.mapData);
// log client map update time
duration = Util.timeStop(logKeyClientMapData);
Util.log(logKeyClientMapData, {duration: duration, type: 'client', description: 'update map'});
}
// get the current update delay (this can change if a user is inactive)
var mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
// init new trigger
updateTimeouts.mapUpdate = setTimeout(function(){
triggerMapUpdatePing();
}, mapUpdateDelay);
// initial start for the userUpdate trigger
// this should only be called at the first time!
if(updateTimeouts.userUpdate === 0){
// start user update trigger after map loaded
updateTimeouts.userUpdate = setTimeout(function(){
triggerUserUpdatePing();
}, 3000);
}
}
}).fail(handleAjaxErrorResponse);
};
// ping for user data update =======================================================
var triggerUserUpdatePing = function(){
// IMPORTANT: Get user data for ONE map that is currently visible
// On later releases this can be easy changed to "full update" all maps for a user
//
var mapIds = [];
var activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapIds = [ activeMap.data('id') ];
}
var updatedUserData = {
mapIds: mapIds,
systemData: Util.getCurrentSystemData(),
characterMapData: {
mapTracking: (locationToggle.is(':checked') ? 1 : 0) // location tracking
}
};
Util.timeStart(logKeyServerUserData);
$.ajax({
type: 'POST',
url: Init.path.updateUserData,
data: updatedUserData,
dataType: 'json'
}).done(function(data){
// log request time
var duration = Util.timeStop(logKeyServerUserData);
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
if(data.error.length > 0){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined){
// store current user data global (cache)
var userData = Util.setCurrentUserData(data.userData);
// store current map user data (cache)
if(data.mapUserData !== undefined){
Util.setCurrentMapUserData(data.mapUserData);
}
// start log
Util.timeStart(logKeyClientUserData);
// active character data found
mapModule.updateMapModuleData();
// log client user data update time
duration = Util.timeStop(logKeyClientUserData);
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
// update system info panels
if(data.system){
mapModule.updateSystemModuleData(data.system);
}
// get the current update delay (this can change if a user is inactive)
var mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
// init new trigger
updateTimeouts.userUpdate = setTimeout(function(){
triggerUserUpdatePing();
}, mapUserUpdateDelay);
}
}
}).fail(handleAjaxErrorResponse);
};
let locationToggle = $('#' + Util.config.headMapTrackingId);
/**
* Ajax error response handler function for main-ping functions
@@ -277,16 +148,16 @@ define([
* @param status
* @param error
*/
var handleAjaxErrorResponse = function(jqXHR, status, error){
let handleAjaxErrorResponse = (jqXHR, status, error) => {
// clear both main update request trigger timer
clearUpdateTimeouts();
var reason = status + ' ' + jqXHR.status + ': ' + error;
var errorData = [];
let reason = status + ' ' + jqXHR.status + ': ' + error;
let errorData = [];
if(jqXHR.responseJSON){
// handle JSON
var errorObj = $.parseJSON(jqXHR.responseText);
let errorObj = $.parseJSON(jqXHR.responseText);
if(
errorObj.error &&
@@ -306,12 +177,184 @@ define([
};
/**
* init (schedule) next MapUpdate Ping
*/
let initMapUpdatePing = () => {
// get the current update delay (this can change if a user is inactive)
let delay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
updateTimeouts.mapUpdate = setTimeout(() => {
triggerMapUpdatePing();
}, delay);
};
// ping for main map update ========================================================
let triggerMapUpdatePing = () => {
// check each interval if map module is still available
let check = $('#' + mapModule.attr('id')).length;
if(check === 0){
// program crash stop any update
return;
}
// get updated map data
let updatedMapData = {
mapData: mapModule.getMapModuleDataForUpdate(),
getUserData: ( Util.getCurrentUserData() ) ? 0 : 1
};
// check if mapUpdate trigger should be send
// -> if "syncType" === "ajax" -> send always
// -> if "syncType" === "webSocket" -> send initial AND on map changes
if(
Util.getSyncType() === 'ajax' ||
(
Util.getSyncType() === 'webSocket' &&
updatedMapData.mapData.length
)
){
// start log
Util.timeStart(logKeyServerMapData);
// store updatedMapData
$.ajax({
type: 'POST',
url: Init.path.updateMapData,
data: updatedMapData,
dataType: 'json'
}).done((data) => {
// log request time
let duration = Util.timeStop(logKeyServerMapData);
Util.log(logKeyServerMapData, {duration: duration, type: 'server', description: 'request map data'});
Util.setSyncStatus('ajax:get');
if(
data.error &&
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined) {
// store current user data global (cache)
Util.setCurrentUserData(data.userData);
}
// map data found
Util.setCurrentMapData(data.mapData);
// load/update main map module
mapModule.updateMapModule();
// get the current update delay (this can change if a user is inactive)
let mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
// init new trigger
initMapUpdatePing();
// initial start for the userUpdate trigger
// this should only be called at the first time!
if(updateTimeouts.userUpdate === 0){
// start user update trigger after map loaded
updateTimeouts.userUpdate = setTimeout(() => {
triggerUserUpdatePing();
}, 1000);
}
}
}).fail(handleAjaxErrorResponse);
}else{
// skip this mapUpdate trigger and init next one
initMapUpdatePing();
}
};
// ping for user data update =======================================================
let triggerUserUpdatePing = () => {
// IMPORTANT: Get user data for ONE map that is currently visible
// On later releases this can be easy changed to "full update" all maps for a user
//
let mapIds = [];
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapIds = [ activeMap.data('id') ];
}
let updatedUserData = {
mapIds: mapIds,
systemData: Util.getCurrentSystemData(),
characterMapData: {
mapTracking: (locationToggle.is(':checked') ? 1 : 0) // location tracking
}
};
Util.timeStart(logKeyServerUserData);
$.ajax({
type: 'POST',
url: Init.path.updateUserData,
data: updatedUserData,
dataType: 'json'
}).done((data) => {
// log request time
let duration = Util.timeStop(logKeyServerUserData);
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
if(data.error.length > 0){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined){
// store current user data global (cache)
let userData = Util.setCurrentUserData(data.userData);
// store current map user data (cache)
if(data.mapUserData !== undefined){
Util.setCurrentMapUserData(data.mapUserData);
}
// active character data found
mapModule.updateMapModuleData();
// update system info panels
if(data.system){
mapModule.updateSystemModuleData(data.system);
}
// get the current update delay (this can change if a user is inactive)
let mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
// init new trigger
updateTimeouts.userUpdate = setTimeout(() => {
triggerUserUpdatePing();
}, mapUserUpdateDelay);
}
}
}).fail(handleAjaxErrorResponse);
};
/**
* clear both main update timeouts
* -> stop program from working -> shutdown
*/
var clearUpdateTimeouts = function(){
for(var intervalKey in updateTimeouts) {
let clearUpdateTimeouts = () => {
for(let intervalKey in updateTimeouts) {
if(updateTimeouts.hasOwnProperty(intervalKey)){
clearTimeout( updateTimeouts[intervalKey] );

View File

@@ -19,7 +19,7 @@ define([
'use strict';
var config = {
let config = {
dynamicElementWrapperId: 'pf-dialog-wrapper', // parent Element for dynamic content (dialogs,..)
mapTabElementId: 'pf-map-tab-element', // id for map tab element (tabs + content)
mapTabBarId: 'pf-map-tabs', // id for map tab bar
@@ -45,15 +45,14 @@ define([
};
var mapTabChangeBlocked = false; // flag for preventing map tab switch
let mapTabChangeBlocked = false; // flag for preventing map tab switch
/**
* get all maps for a maps module
* @returns {*}
*/
$.fn.getMaps = function(){
var maps = $(this).find('.' + config.mapClass);
return maps;
return $(this).find('.' + config.mapClass);
};
/**
@@ -61,8 +60,7 @@ define([
* @returns {*}
*/
$.fn.getActiveMap = function(){
var map = $(this).find('.active.' + config.mapTabContentClass + ' .' + config.mapClass);
let map = $(this).find('.active.' + config.mapTabContentClass + ' .' + config.mapClass);
if(map.length === 0){
map = false;
@@ -92,7 +90,7 @@ define([
* @param tabContentElement
* @param callback
*/
var removeSystemModules = function(tabContentElement, callback){
let removeSystemModules = function(tabContentElement, callback){
tabContentElement.find('.' + config.moduleClass).velocity('transition.slideDownOut', {
duration: Init.animationSpeed.mapModule,
complete: function(tempElement){
@@ -109,12 +107,12 @@ define([
* clears and updates the system info element (signature table, system info,...)
* @param tabContentElement
*/
var drawSystemModules = function(tabContentElement){
var currentSystemData = Util.getCurrentSystemData();
let drawSystemModules = function(tabContentElement){
let currentSystemData = Util.getCurrentSystemData();
// get Table cell for system Info
var firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
var secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
let firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
let secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
// draw system info module
firstCell.drawSystemInfoModule(currentSystemData.mapId, currentSystemData.systemData);
@@ -138,16 +136,16 @@ define([
/**
* set observer for each module
*/
var setModuleObserver = function(){
let setModuleObserver = function(){
// toggle height for a module
$(document).off('click.toggleModuleHeight').on('click.toggleModuleHeight', '.' + config.moduleClass, function(e){
var moduleElement = $(this);
let moduleElement = $(this);
// get click position
var posX = moduleElement.offset().left;
var posY = moduleElement.offset().top;
var clickX = e.pageX - posX;
var clickY = e.pageY - posY;
let posX = moduleElement.offset().left;
let posY = moduleElement.offset().top;
let clickX = e.pageX - posX;
let clickY = e.pageY - posY;
// check for top-left click
if(clickX <= 8 && clickY <= 8){
@@ -159,7 +157,7 @@ define([
}
if(moduleElement.hasClass( config.moduleClosedClass )){
var moduleHeight = moduleElement.data('origHeight');
let moduleHeight = moduleElement.data('origHeight');
moduleElement.velocity('finish').velocity({
height: [ moduleHeight + 'px', [ 400, 15 ] ]
},{
@@ -191,15 +189,19 @@ define([
* @returns {boolean}
*/
$.fn.updateMapModuleData = function(){
var mapModule = $(this);
let mapModule = $(this);
// performance logging (time measurement)
let logKeyClientUserData = Init.performanceLogging.keyClientUserData;
Util.timeStart(logKeyClientUserData);
// get all active map elements for module
var mapElement = mapModule.getActiveMap();
let mapElement = mapModule.getActiveMap();
if(mapElement !== false){
var mapId = mapElement.data('id');
let mapId = mapElement.data('id');
var currentMapUserData = Util.getCurrentMapUserData(mapId);
let currentMapUserData = Util.getCurrentMapUserData(mapId);
// update map with current user data
if(currentMapUserData){
@@ -207,6 +209,10 @@ define([
}
}
// log client user data update time
let duration = Util.timeStop(logKeyClientUserData);
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
return true;
};
@@ -215,11 +221,11 @@ define([
* @param systemData
*/
$.fn.updateSystemModuleData = function(systemData){
var mapModule = $(this);
let mapModule = $(this);
if(systemData){
// check if current open system is still the requested info system
var currentSystemData = Util.getCurrentSystemData();
let currentSystemData = Util.getCurrentSystemData();
if(currentSystemData){
if(systemData.id === currentSystemData.systemData.id){
@@ -237,7 +243,7 @@ define([
$.fn.initContentStructure = function(){
return this.each(function(){
// init bootstrap Grid
var contentStructure = $('<div>', {
let contentStructure = $('<div>', {
class: ['row', config.mapTabContentRow].join(' ')
}).append(
$('<div>', {
@@ -259,17 +265,17 @@ define([
* @param options
* @returns {*|jQuery|HTMLElement}
*/
var getTabElement = function(options){
var tabElement = $('<div>', {
let getTabElement = function(options){
let tabElement = $('<div>', {
id: config.mapTabElementId
});
var tabBar = $('<ul>', {
let tabBar = $('<ul>', {
class: ['nav', 'nav-tabs'].join(' '),
id: options.barId
}).attr('role', 'tablist');
var tabContent = $('<div>', {
let tabContent = $('<div>', {
class: 'tab-content'
}).attr('data-map-tabs', options.barId);
@@ -284,7 +290,7 @@ define([
* @param options
*/
$.fn.updateTabData = function(options){
var tabElement = $(this);
let tabElement = $(this);
// set "main" data
tabElement.data('map-id', options.id).data('updated', options.updated);
@@ -293,17 +299,17 @@ define([
tabElement.attr('href', '#' + config.mapTabIdPrefix + options.id);
// change "map" icon
var mapIconElement = tabElement.find('.' + config.mapTabIconClass);
let mapIconElement = tabElement.find('.' + config.mapTabIconClass);
mapIconElement.removeClass().addClass([config.mapTabIconClass, 'fa', 'fa-fw', options.icon].join(' '));
// change "shared" icon
var mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
let mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
mapSharedIconElement.hide();
// check if the map is a "shared" map
if(options.access){
if(
options.access.user.length > 1 ||
options.access.character.length > 1 ||
options.access.corporation.length > 1 ||
options.access.alliance.length > 1
){
@@ -312,14 +318,14 @@ define([
}
// change map name label
var tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
let tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
tabLinkTextElement.text(options.name);
// change tabClass
var listElement = tabElement.parent();
let listElement = tabElement.parent();
// new tab classes
var tabClasses = [config.mapTabClass, options.type.classTab ];
let tabClasses = [config.mapTabClass, options.type.classTab ];
// check if tab was "active" before
if( listElement.hasClass('active') ){
@@ -332,7 +338,7 @@ define([
tabLinkTextElement.attr('title', options.type.name + ' map');
}
var mapTooltipOptions = {
let mapTooltipOptions = {
placement: 'bottom',
container: 'body',
trigger: 'hover',
@@ -353,36 +359,36 @@ define([
* @returns {{listElement: (*|void), contentElement: (*|HTMLElement)}}
*/
$.fn.addTab = function(options){
var tabElement = $(this);
var tabBar = tabElement.find('ul.nav-tabs');
var tabContent = tabElement.find('div.tab-content');
let tabElement = $(this);
let tabBar = tabElement.find('ul.nav-tabs');
let tabContent = tabElement.find('div.tab-content');
var listElement = $('<li>').attr('role', 'presentation');
let listElement = $('<li>').attr('role', 'presentation');
if(options.right === true){
listElement.addClass('pull-right');
}
// link element
var linkElement = $('<a>').attr('role', 'tab');
let linkElement = $('<a>').attr('role', 'tab');
// map icon element
var mapIconElement = $('<i>', {
let mapIconElement = $('<i>', {
class: config.mapTabIconClass
});
// map shared icon element
var mapSharedIconElement = $('<i>', {
let mapSharedIconElement = $('<i>', {
class: [config.mapTabSharedIconClass, 'fa', 'fa-fw', 'fa-share-alt'].join(' '),
title: 'shared map'
});
// text element
var textElement = $('<span>', {
let textElement = $('<span>', {
class: config.mapTabLinkTextClass
});
var newListElement = listElement.append(
let newListElement = listElement.append(
linkElement.append(mapIconElement).append(textElement).append(mapSharedIconElement)
);
@@ -392,7 +398,7 @@ define([
linkElement.updateTabData(options);
// tabs content =======================================================
var contentElement = $('<div>', {
let contentElement = $('<div>', {
id: config.mapTabIdPrefix + parseInt( options.id ),
class: [config.mapTabContentClass].join(' ')
});
@@ -414,12 +420,12 @@ define([
}
if(mapTabChangeBlocked === false){
var tabLinkElement = $(this);
var mapId = tabLinkElement.data('map-id');
let tabLinkElement = $(this);
let mapId = tabLinkElement.data('map-id');
// ignore "add" tab. no need for map change
if(mapId > 0){
var mapElement = $('#' + config.mapTabElementId).getActiveMap();
let mapElement = $('#' + config.mapTabElementId).getActiveMap();
if(mapId !== mapElement.data('id')){
// block tabs until switch is done
@@ -451,17 +457,17 @@ define([
* @param mapId
*/
$.fn.deleteTab = function(mapId){
var tabElement = $(this);
var linkElement = tabElement.find('a[href="#' + config.mapTabIdPrefix + mapId + '"]');
var deletedTabName = '';
let tabElement = $(this);
let linkElement = tabElement.find('a[href="#' + config.mapTabIdPrefix + mapId + '"]');
let deletedTabName = '';
if(linkElement.length > 0){
deletedTabName = linkElement.find('.' + config.mapTabLinkTextClass).text();
var liElement = linkElement.parent();
var contentElement = tabElement.find('div[id="' + config.mapTabIdPrefix + mapId + '"]');
let liElement = linkElement.parent();
let contentElement = tabElement.find('div[id="' + config.mapTabIdPrefix + mapId + '"]');
var findNewActiveTab = false;
let findNewActiveTab = false;
// check if liElement was active
if(liElement.hasClass('active')){
// search any remaining li element and set active
@@ -486,15 +492,15 @@ define([
* clear all active maps
*/
$.fn.clearMapModule = function(){
var mapModuleElement = $(this);
var tabMapElement = $('#' + config.mapTabElementId);
let mapModuleElement = $(this);
let tabMapElement = $('#' + config.mapTabElementId);
if(tabMapElement.length > 0){
var tabElements = mapModuleElement.getMapTabElements();
let tabElements = mapModuleElement.getMapTabElements();
for(var i = 0; i < tabElements.length; i++){
var tabElement = $(tabElements[i]);
var mapId = tabElement.data('map-id');
for(let i = 0; i < tabElements.length; i++){
let tabElement = $(tabElements[i]);
let mapId = tabElement.data('map-id');
if(mapId > 0){
tabMapElement.deleteTab(mapId);
@@ -505,43 +511,52 @@ define([
/**
* load/update map module into element (all maps)
* @param mapData
* @returns {boolean}
*/
$.fn.updateMapModule = function(mapData){
if(mapData.length === 0){
return true;
}
$.fn.updateMapModule = function(){
let mapModuleElement = $(this);
// store current map data global (cache)
// temp store current map data to prevent data-change while function execution!
var tempMapData = Util.setCurrentMapData(mapData);
let tempMapData = Util.getCurrentMapData();
var mapModuleElement = $(this);
if(tempMapData.length === 0){
// clear all existing maps
mapModuleElement.clearMapModule();
// no map data available -> show "new map" dialog
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
return true;
}
// performance logging (time measurement)
let logKeyClientMapData = Init.performanceLogging.keyClientMapData;
Util.timeStart(logKeyClientMapData);
// check if tabs module is already loaded
var tabMapElement = $('#' + config.mapTabElementId);
let tabMapElement = $('#' + config.mapTabElementId);
// check if tabs have changed
var tabsChanged = false;
let tabsChanged = false;
if(tabMapElement.length > 0){
// tab element already exists
var tabElements = mapModuleElement.getMapTabElements();
let tabElements = mapModuleElement.getMapTabElements();
// map ID that is currently active
var activeMapId = 0;
let activeMapId = 0;
// mapIds that are currently active
var activeMapIds = [];
let activeMapIds = [];
// check whether a tab/map is still active
for(var i = 0; i < tabElements.length; i++){
var tabElement = $(tabElements[i]);
var mapId = tabElement.data('map-id');
for(let i = 0; i < tabElements.length; i++){
let tabElement = $(tabElements[i]);
let mapId = tabElement.data('map-id');
if(mapId > 0){
var tabMapData = Util.getCurrentMapData(mapId);
let tabMapData = Util.getCurrentMapData(mapId);
if(tabMapData !== false){
// map data available ->
@@ -553,7 +568,7 @@ define([
}
}else{
// map data not available -> remove tab
var deletedTabName = tabMapElement.deleteTab(mapId);
let deletedTabName = tabMapElement.deleteTab(mapId);
tabsChanged = true;
@@ -569,7 +584,7 @@ define([
if( activeMapIds.indexOf( data.config.id ) === -1 ){
// add new map tab
var newTabElements = tabMapElement.addTab(data.config);
let newTabElements = tabMapElement.addTab(data.config);
// check if there is any active map yet (this is not the case
// when ALL maps are removed AND new maps are added in one call
@@ -596,11 +611,11 @@ define([
if(activeMapId === 0){
activeMapId = Util.getMapModule().getActiveMap().data('id');
}
var activeMapData = Util.getCurrentMapData(activeMapId);
let activeMapData = Util.getCurrentMapData(activeMapId);
if(activeMapData !== false){
// update active map with new mapData
var currentTabContentElement = $('#' + config.mapTabIdPrefix + activeMapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + activeMapId);
$( currentTabContentElement).loadMap( activeMapData, {} );
}
@@ -608,21 +623,21 @@ define([
// create Tab Element
tabsChanged = true;
var options = {
let options = {
barId: config.mapTabBarId
};
tabMapElement = getTabElement(options);
// add new tab for each map
for(var j = 0; j < tempMapData.length; j++){
for(let j = 0; j < tempMapData.length; j++){
var data = tempMapData[j];
let data = tempMapData[j];
tabMapElement.addTab(data.config);
}
// add "add" button
var tabAddOptions = {
let tabAddOptions = {
id: 0,
type: {
classTab: MapUtil.getInfoForMap( 'standard', 'classTab')
@@ -636,14 +651,14 @@ define([
mapModuleElement.prepend(tabMapElement);
var currentUserData = Util.getCurrentUserData();
var promiseStore = MapUtil.getLocaleData('character', currentUserData.character.id);
let currentUserData = Util.getCurrentUserData();
let promiseStore = MapUtil.getLocaleData('character', currentUserData.character.id);
promiseStore.then(function(data) {
// array key where map data is available (0 == first map found)
var mapDataIndex = 0;
let mapDataIndex = 0;
// tab dom selector
var mapKeyTabSelector = 'first';
let mapKeyTabSelector = 'first';
if(
data &&
@@ -656,7 +671,7 @@ define([
// ==============================================================
// this new created module
var tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
let tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
// set observer for manually triggered map events
tabContentElements.setTabContentObserver();
@@ -673,7 +688,7 @@ define([
if(tabsChanged === true){
// remove previous event handlers
var allTabElements = mapModuleElement.getMapTabElements();
let allTabElements = mapModuleElement.getMapTabElements();
allTabElements.off('show.bs.tab');
allTabElements.off('shown.bs.tab');
allTabElements.off('hide.bs.tab');
@@ -681,11 +696,11 @@ define([
// check for "new map" action before tap-change
allTabElements.on('show.bs.tab', function (e) {
var mapId = $(e.target).data('map-id');
let mapId = $(e.target).data('map-id');
if(mapId > 0){
// save mapId as new "default" (local storage)
var userData = MapUtil.storeDefaultMapId(mapId);
let userData = MapUtil.storeDefaultMapId(mapId);
}else{
// add new Tab selected
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
@@ -695,17 +710,17 @@ define([
// load new map right after tab-change
allTabElements.on('shown.bs.tab', function (e) {
var mapId = $(e.target).data('map-id');
var tabMapData = Util.getCurrentMapData(mapId);
let mapId = $(e.target).data('map-id');
let tabMapData = Util.getCurrentMapData(mapId);
if(tabMapData !== false){
// load map
var currentTabContentElement = $('#' + config.mapTabIdPrefix + mapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + mapId);
$( currentTabContentElement).loadMap( tabMapData, {showAnimation: true} );
// "wake up" scrollbar for map and get previous state back
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
let scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
$(scrollableElement).mCustomScrollbar( 'update');
}else{
// no map data found -> remove tab
@@ -714,20 +729,24 @@ define([
});
allTabElements.on('hide.bs.tab', function (e) {
var newMapId = $(e.relatedTarget).data('map-id');
var oldMapId = $(e.target).data('map-id');
let newMapId = $(e.relatedTarget).data('map-id');
let oldMapId = $(e.target).data('map-id');
// skip "add button"
if(newMapId > 0){
var currentTabContentElement = $('#' + config.mapTabIdPrefix + oldMapId);
let currentTabContentElement = $('#' + config.mapTabIdPrefix + oldMapId);
// disable scrollbar for map that will be hidden. "freeze" current state
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
let scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
$(scrollableElement).mCustomScrollbar( 'disable' );
}
});
}
// log client map update time
let duration = Util.timeStop(logKeyClientMapData);
Util.log(logKeyClientMapData, {duration: duration, type: 'client', description: 'update map'});
return true;
};
@@ -737,14 +756,13 @@ define([
* @returns {Array}
*/
$.fn.getMapModuleDataForUpdate = function(){
// get all active map elements for module
var mapElements = $(this).getMaps();
let mapElements = $(this).getMaps();
var data = [];
for(var i = 0; i < mapElements.length; i++){
let data = [];
for(let i = 0; i < mapElements.length; i++){
// get all changed (system / connection) data from this map
var mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true});
let mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true});
if(mapData !== false){

View File

@@ -27,7 +27,7 @@ define([
'use strict';
var config = {
let config = {
// page structure slidebars-menu classes
pageId: 'sb-site',
pageSlidebarClass: 'sb-slidebar',
@@ -64,8 +64,8 @@ define([
dynamicElementWrapperId: 'pf-dialog-wrapper'
};
var programStatusCounter = 0; // current count down in s until next status change is possible
var programStatusInterval = false; // interval timer until next status change is possible
let programStatusCounter = 0; // current count down in s until next status change is possible
let programStatusInterval = false; // interval timer until next status change is possible
/**
@@ -119,7 +119,7 @@ define([
* @param title
* @returns {JQuery|*|jQuery}
*/
var getMenuHeadline = function(title){
let getMenuHeadline = function(title){
return $('<div>', {
class: 'panel-heading'
}).prepend(
@@ -211,7 +211,7 @@ define([
css: {width: '1.23em'}
})
).on('click', function(){
var fullScreenElement = $('body');
let fullScreenElement = $('body');
requirejs(['jquery', 'fullScreen'], function($) {
if($.fullscreen.isFullScreen()){
@@ -385,10 +385,9 @@ define([
* load page header
*/
$.fn.loadHeader = function(){
let pageElement = $(this);
var pageElement = $(this);
var moduleData = {
let moduleData = {
id: config.pageHeaderId,
logo: function(){
// render svg logo
@@ -403,14 +402,14 @@ define([
mapTrackingId: Util.config.headMapTrackingId
};
var headRendered = Mustache.render(TplHead, moduleData);
let headRendered = Mustache.render(TplHead, moduleData);
pageElement.prepend(headRendered);
// init header =====================================================================
// init slide menus
var slideMenu = new $.slidebars({
let slideMenu = new $.slidebars({
scrollLock: false
});
@@ -445,7 +444,7 @@ define([
});
// tracking toggle
var mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
let mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
mapTrackingCheckbox.bootstrapToggle({
size: 'mini',
on: 'on',
@@ -461,10 +460,10 @@ define([
mapTrackingCheckbox.bootstrapToggle('on');
mapTrackingCheckbox.on('change', function(e) {
var value = $(this).is(':checked');
var tracking = 'off';
var trackingText = 'Your current location will not actually be added';
var trackingType = 'info';
let value = $(this).is(':checked');
let tracking = 'off';
let trackingText = 'Your current location will not actually be added';
let trackingType = 'info';
if(value){
tracking = 'on';
trackingText = 'New connections will actually be added';
@@ -476,7 +475,7 @@ define([
// init all tooltips
var tooltipElements = $('#' + config.pageHeaderId).find('[title]');
let tooltipElements = $('#' + config.pageHeaderId).find('[title]');
tooltipElements.tooltip({
placement: 'bottom',
delay: {
@@ -492,15 +491,15 @@ define([
* load page footer
*/
$.fn.loadFooter = function(){
var pageElement = $(this);
let pageElement = $(this);
var moduleData = {
let moduleData = {
id: config.pageFooterId,
footerLicenceLinkClass: config.footerLicenceLinkClass,
currentYear: new Date().getFullYear()
};
var headRendered = Mustache.render(TplFooter, moduleData);
let headRendered = Mustache.render(TplFooter, moduleData);
pageElement.prepend(headRendered);
@@ -517,12 +516,12 @@ define([
/**
* catch all global document events
*/
var setDocumentObserver = function(){
let setDocumentObserver = function(){
// on "full-screen" change event
$(document).on('fscreenchange', function(e, state, elem){
var menuButton = $('#' + Util.config.menuButtonFullScreenId);
let menuButton = $('#' + Util.config.menuButtonFullScreenId);
if(state === true){
// full screen active
@@ -586,9 +585,9 @@ define([
$(document).on('pf:menuShowMapSettings', function(e, data){
// show map edit dialog or edit map
var mapData = false;
let mapData = false;
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapData = Util.getCurrentMapData( activeMap.data('id') );
@@ -600,9 +599,9 @@ define([
$(document).on('pf:menuDeleteMap', function(e){
// delete current active map
var mapData = false;
let mapData = false;
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
if(activeMap){
mapData = activeMap.getMapDataFromClient({forceData: true});
@@ -620,7 +619,7 @@ define([
$(document).on('pf:menuLogout', function(e, data){
var clearCookies = false;
let clearCookies = false;
if(
typeof data === 'object' &&
data.hasOwnProperty('clearCookies')
@@ -642,10 +641,10 @@ define([
// update header links with current map data
$(document).on('pf:updateHeaderMapData', function(e, data){
var activeMap = Util.getMapModule().getActiveMap();
let activeMap = Util.getMapModule().getActiveMap();
var userCount = 0;
var currentLocationData = {};
let userCount = 0;
let currentLocationData = {};
// show active user just for the current active map
if(
@@ -662,7 +661,7 @@ define([
// shutdown the program -> show dialog
$(document).on('pf:shutdown', function(e, data){
// show shutdown dialog
var options = {
let options = {
buttons: {
logout: {
label: '<i class="fa fa-fw fa-refresh"></i> restart',
@@ -724,21 +723,21 @@ define([
* updates the header with current user data
*/
$.fn.updateHeaderUserData = function(){
var userData = Util.getCurrentUserData();
let userData = Util.getCurrentUserData();
var userInfoElement = $('.' + config.headUserCharacterClass);
var currentCharacterId = userInfoElement.data('characterId');
var currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
var newCharacterId = 0;
var newCharacterName = '';
let userInfoElement = $('.' + config.headUserCharacterClass);
let currentCharacterId = userInfoElement.data('characterId');
let currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
let newCharacterId = 0;
let newCharacterName = '';
var userShipElement = $('.' + config.headUserShipClass);
var currentShipId = userShipElement.data('shipId');
var newShipId = 0;
var newShipName = '';
let userShipElement = $('.' + config.headUserShipClass);
let currentShipId = userShipElement.data('shipId');
let newShipId = 0;
let newShipName = '';
// function for header element toggle animation
var animateHeaderElement = function(element, callback, triggerShow){
let animateHeaderElement = function(element, callback, triggerShow){
element.show().velocity('stop').velocity({
opacity: 0
@@ -784,14 +783,14 @@ define([
updateMapTrackingToggle(userData.character.logLocation);
}
var newCharactersOptionIds = userData.characters.map(function(data){
let newCharactersOptionIds = userData.characters.map(function(data){
return data.id;
});
// update user character data ---------------------------------------------------
if(currentCharactersOptionIds.toString() !== newCharactersOptionIds.toString()){
var currentCharacterChanged = false;
let currentCharacterChanged = false;
if(currentCharacterId !== newCharacterId){
currentCharacterChanged = true;
}
@@ -814,7 +813,7 @@ define([
// update user ship data --------------------------------------------------------
if(currentShipId !== newShipId){
var showShipElement = true;
let showShipElement = true;
if(newShipId === 0){
showShipElement = false;
}
@@ -834,8 +833,8 @@ define([
* update "map tracking" toggle in header
* @param status
*/
var updateMapTrackingToggle = function(status){
var mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
let updateMapTrackingToggle = function(status){
let mapTrackingCheckbox = $('#' + Util.config.headMapTrackingId);
if(status === true){
mapTrackingCheckbox.bootstrapToggle('enable');
}else{
@@ -846,7 +845,7 @@ define([
/**
* delete active character log for the current user
*/
var deleteLog = function(){
let deleteLog = function(){
$.ajax({
type: 'POST',
@@ -862,9 +861,9 @@ define([
* update the "active user" badge in header
* @param userCount
*/
var updateHeaderActiveUserCount = function(userCount){
var activeUserElement = $('.' + config.headActiveUserClass);
var badge = activeUserElement.find('.badge');
let updateHeaderActiveUserCount = function(userCount){
let activeUserElement = $('.' + config.headActiveUserClass);
let badge = activeUserElement.find('.badge');
if(badge.data('userCount') !== userCount){
badge.data('userCount', userCount);
@@ -884,13 +883,13 @@ define([
* update the "current location" element in head
* @param locationData
*/
var updateHeaderCurrentLocation = function(locationData){
var currentLocationElement = $('#' + Util.config.headCurrentLocationId);
var linkElement = currentLocationElement.find('a');
var textElement = linkElement.find('span');
let updateHeaderCurrentLocation = function(locationData){
let currentLocationElement = $('#' + Util.config.headCurrentLocationId);
let linkElement = currentLocationElement.find('a');
let textElement = linkElement.find('span');
var tempSystemName = (locationData.currentSystemName) ? locationData.currentSystemName : false;
var tempSystemId = (locationData.currentSystemId) ? locationData.currentSystemId : 0;
let tempSystemName = (locationData.currentSystemName) ? locationData.currentSystemName : false;
let tempSystemId = (locationData.currentSystemId) ? locationData.currentSystemId : 0;
if(
linkElement.data('systemName') !== tempSystemName ||
@@ -915,7 +914,7 @@ define([
/**
* shows a test notification for desktop messages
*/
var notificationTest = function(){
let notificationTest = function(){
Util.showNotify({
title: 'Test Notification',
text: 'Accept browser security question'},
@@ -930,17 +929,17 @@ define([
* set event listener if the program tab is active or not
* this is used to lower the update ping cycle to reduce server load
*/
var initTabChangeObserver = function(){
let initTabChangeObserver = function(){
// increase the timer if a user is inactive
var increaseTimer = 10000;
let increaseTimer = 10000;
// timer keys
var mapUpdateKey = 'UPDATE_SERVER_MAP';
var mapUserUpdateKey = 'UPDATE_SERVER_USER_DATA';
let mapUpdateKey = 'UPDATE_SERVER_MAP';
let mapUserUpdateKey = 'UPDATE_SERVER_USER_DATA';
// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
let hidden, visibilityChange;
if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
hidden = 'hidden';
visibilityChange = 'visibilitychange';
@@ -997,86 +996,74 @@ define([
* @param status
*/
$.fn.setProgramStatus = function(status){
var statusElement = $('.' + config.headProgramStatusClass);
var icon = statusElement.find('i');
var textElement = statusElement.find('span');
let statusElement = $('.' + config.headProgramStatusClass);
let icon = statusElement.find('i');
let textElement = statusElement.find('span');
var iconClass = false;
var textClass = false;
var text = '';
let iconClass = false;
let textClass = false;
switch(status){
case 'online':
if( ! statusElement.hasClass('txt-color-green')){
iconClass = 'fa-wifi';
textClass = 'txt-color-green';
text = 'online';
}
iconClass = 'fa-wifi';
textClass = 'txt-color-green';
break;
case 'slow connection':
case 'problem':
if( ! statusElement.hasClass('txt-color-orange')){
iconClass = 'fa-warning';
textClass = 'txt-color-orange';
text = 'problem';
}
iconClass = 'fa-warning';
textClass = 'txt-color-orange';
break;
case 'offline':
if( ! statusElement.hasClass('txt-color-red')){
iconClass = 'fa-bolt';
textClass = 'txt-color-red';
text = 'offline';
}
iconClass = 'fa-bolt';
textClass = 'txt-color-red';
break;
}
// change status, on status changed
if(iconClass !== false){
// "warnings" and "errors" always have priority -> ignore/clear interval
if(
textClass === 'txt-color-orange' ||
textClass === 'txt-color-red'
){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
// "problem" and "offline" always have priority -> ignore/clear interval
if(
status === 'problem' ||
status === 'offline'
){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
if( statusElement.data('status') !== status ){
// status has changed
if(! programStatusInterval){
if(! statusElement.hasClass(textClass) ){
let timer = function(){
// change status on first timer iteration
if(programStatusCounter === Init.timer.PROGRAM_STATUS_VISIBLE){
statusElement.velocity('stop').velocity('fadeOut', {
duration: Init.animationSpeed.headerLink,
complete: function(){
// store current status
statusElement.data('status', status);
statusElement.removeClass('txt-color-green txt-color-orange txt-color-red');
icon.removeClass('fa-wifi fa-warning fa-bolt');
statusElement.addClass(textClass);
icon.addClass(iconClass);
textElement.text(status);
}
}).velocity('fadeIn', {
duration: Init.animationSpeed.headerLink
});
}
// decrement counter
programStatusCounter -= 1000;
if(programStatusCounter <= 0){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
};
if(! programStatusInterval){
var timer = function(){
// change status on first timer iteration
if(programStatusCounter === Init.timer.PROGRAM_STATUS_VISIBLE){
statusElement.velocity('stop').velocity('fadeOut', {
duration: Init.animationSpeed.headerLink,
complete: function(){
statusElement.removeClass('txt-color-green txt-color-orange txt-color-red');
icon.removeClass('fa-wifi fa-warning fa-bolt');
statusElement.addClass(textClass);
icon.addClass(iconClass);
textElement.text(text);
}
}).velocity('fadeIn', {
duration: Init.animationSpeed.headerLink
});
}
// decrement counter
programStatusCounter -= 1000;
if(programStatusCounter <= 0){
clearInterval(programStatusInterval);
programStatusInterval = false;
}
};
if(! programStatusInterval){
programStatusCounter = Init.timer.PROGRAM_STATUS_VISIBLE;
programStatusInterval = setInterval(timer, 1000);
}
programStatusCounter = Init.timer.PROGRAM_STATUS_VISIBLE;
programStatusInterval = setInterval(timer, 1000);
}
}
}

View File

@@ -12,7 +12,7 @@ define([
], function($, Init, Util, Render, bootbox, MapUtil) {
'use strict';
var config = {
let config = {
// map dialog
newMapDialogId: 'pf-map-dialog', // id for map settings dialog
dialogMapCreateContainerId: 'pf-map-dialog-create', // id for the "new map" container
@@ -43,11 +43,11 @@ define([
* @param filename
* @returns {string}
*/
var formatFilename = function(filename){
let formatFilename = function(filename){
filename = filename.replace(/[^a-zA-Z0-9]/g,'_');
var nowDate = new Date();
var filenameDate = nowDate.toISOString().slice(0,10).replace(/-/g, '_');
let nowDate = new Date();
let filenameDate = nowDate.toISOString().slice(0,10).replace(/-/g, '_');
return (filename + '_' + filenameDate).replace(/__/g,'_');
};
@@ -60,7 +60,7 @@ define([
$.fn.showMapSettingsDialog = function(mapData, options){
// check if dialog is already open
var mapInfoDialogElement = $('#' + config.newMapDialogId);
let mapInfoDialogElement = $('#' + config.newMapDialogId);
if(!mapInfoDialogElement.is(':visible')){
requirejs([
@@ -69,12 +69,12 @@ define([
'mustache'
], function(templateMapDialog, templateMapSettings, Mustache) {
var dialogTitle = 'Map settings';
let dialogTitle = 'Map settings';
// if there are no maps -> hide settings tab
var hideSettingsTab = false;
var hideEditTab = false;
var hideDownloadTab = false;
let hideSettingsTab = false;
let hideEditTab = false;
let hideDownloadTab = false;
if(mapData === false){
hideSettingsTab = true;
@@ -83,9 +83,9 @@ define([
}
// available map "types" for a new or existing map
var mapTypes = MapUtil.getMapTypes(true);
let mapTypes = MapUtil.getMapTypes(true);
var data = {
let data = {
scope: MapUtil.getMapScopes(),
type: mapTypes,
icon: MapUtil.getMapIcons(),
@@ -95,17 +95,17 @@ define([
};
// render "new map" tab content -------------------------------------------
var contentNewMap = Mustache.render(templateMapSettings, data);
let contentNewMap = Mustache.render(templateMapSettings, data);
// render "edit map" tab content ------------------------------------------
var contentEditMap = Mustache.render(templateMapSettings, data);
let contentEditMap = Mustache.render(templateMapSettings, data);
contentEditMap = $(contentEditMap);
// current map access info
var accessCharacter = [];
var accessCorporation = [];
var accessAlliance = [];
var deleteExpiredConnections = true;
let accessCharacter = [];
let accessCorporation = [];
let accessAlliance = [];
let deleteExpiredConnections = true;
if(mapData !== false){
// set current map information
@@ -178,20 +178,20 @@ define([
formatFilename: function(){
// format filename from "map name" (initial)
return function (mapName, render) {
var filename = render(mapName);
let filename = render(mapName);
return formatFilename(filename);
};
}
};
var contentDialog = Mustache.render(templateMapDialog, data);
let contentDialog = Mustache.render(templateMapDialog, data);
contentDialog = $(contentDialog);
// set tab content
$('#' + config.dialogMapCreateContainerId, contentDialog).html(contentNewMap);
$('#' + config.dialogMapEditContainerId, contentDialog).html(contentEditMap);
var mapInfoDialog = bootbox.dialog({
let mapInfoDialog = bootbox.dialog({
title: dialogTitle,
message: contentDialog,
buttons: {
@@ -205,15 +205,15 @@ define([
callback: function() {
// get the current active form
var form = $('#' + config.newMapDialogId).find('form').filter(':visible');
let form = $('#' + config.newMapDialogId).find('form').filter(':visible');
// validate form
form.validator('validate');
// validate select2 fields (settings tab)
form.find('select').each(function(){
var selectField = $(this);
var selectValues = selectField.val();
let selectField = $(this);
let selectValues = selectField.val();
if(selectValues.length > 0){
selectField.parents('.form-group').removeClass('has-error');
@@ -223,23 +223,23 @@ define([
});
// check whether the form is valid
var formValid = form.isValidForm();
let formValid = form.isValidForm();
if(formValid === true){
// lock dialog
var dialogContent = mapInfoDialog.find('.modal-content');
let dialogContent = mapInfoDialog.find('.modal-content');
dialogContent.showLoadingAnimation();
// get form data
var formData = form.getFormValues();
let formData = form.getFormValues();
// checkbox fix -> settings tab
if( form.find('#' + config.deleteExpiredConnectionsId).length ){
formData.deleteExpiredConnections = formData.hasOwnProperty('deleteExpiredConnections') ? parseInt( formData.deleteExpiredConnections ) : 0;
}
var requestData = {formData: formData};
let requestData = {formData: formData};
$.ajax({
type: 'POST',
@@ -257,7 +257,8 @@ define([
Util.showNotify({title: dialogTitle, text: 'Map: ' + responseData.mapData.mapData.name, type: 'success'});
// update map-tab Element
var tabLinkElement = Util.getMapModule().getMapTabElements(responseData.mapData.mapData.id);
let tabLinkElement = Util.getMapModule().getMapTabElements(responseData.mapData.mapData.id);
if(tabLinkElement.length === 1){
tabLinkElement.updateTabData(responseData.mapData.mapData);
}
@@ -266,7 +267,7 @@ define([
$(document).trigger('pf:closeMenu', [{}]);
}
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': saveMap', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
@@ -297,7 +298,7 @@ define([
// show form messages -------------------------------------
// get current active form(tab)
var form = $('#' + config.newMapDialogId).find('form').filter(':visible');
let form = $('#' + config.newMapDialogId).find('form').filter(':visible');
form.showFormMessage([{type: 'info', message: 'Creating new maps or change settings may take a few seconds'}]);
@@ -312,24 +313,24 @@ define([
}
// init "download tab" ========================================================================
var downloadTabElement = mapInfoDialog.find('#' + config.dialogMapDownloadContainerId);
let downloadTabElement = mapInfoDialog.find('#' + config.dialogMapDownloadContainerId);
if(downloadTabElement.length){
// tab exists
// export map data ------------------------------------------------------------------------
downloadTabElement.find('#' + config.buttonExportId).on('click', { mapData: mapData }, function(e){
var exportForm = $('#' + config.dialogMapExportFormId);
var validExportForm = exportForm.isValidForm();
let exportForm = $('#' + config.dialogMapExportFormId);
let validExportForm = exportForm.isValidForm();
if(validExportForm){
var mapElement = Util.getMapModule().getActiveMap();
let mapElement = Util.getMapModule().getActiveMap();
if(mapElement){
// IMPORTANT: Get map data from client (NOT from global mapData which is available in here)
// -> This excludes some data (e.g. wh statics)
// -> Bring export inline with main map toggle requests
var exportMapData = mapElement.getMapDataFromClient({
let exportMapData = mapElement.getMapDataFromClient({
forceData: true,
getAll: true
});
@@ -349,7 +350,7 @@ define([
// import map data ------------------------------------------------------------------------
// check if "FileReader" API is supported
var importFormElement = downloadTabElement.find('#' + config.dialogMapImportFormId);
let importFormElement = downloadTabElement.find('#' + config.dialogMapImportFormId);
if(window.File && window.FileReader && window.FileList && window.Blob){
// show file info in UI
@@ -357,14 +358,14 @@ define([
e.stopPropagation();
e.preventDefault();
var infoContainerElement = importFormElement.find('#' + config.dialogMapImportInfoId);
let infoContainerElement = importFormElement.find('#' + config.dialogMapImportInfoId);
infoContainerElement.hide().empty();
importFormElement.hideFormMessage('all');
var output = [];
var files = e.target.files;
let output = [];
let files = e.target.files;
for (var i = 0, f; !!(f = files[i]); i++) {
for (let i = 0, f; !!(f = files[i]); i++) {
output.push(( i + 1 ) + '. file: ' + f.name + ' - ' +
f.size + ' bytes; last modified: ' +
f.lastModifiedDate.toLocaleDateString() );
@@ -378,14 +379,14 @@ define([
});
// drag&drop
var importData = {};
let importData = {};
importData.mapData = [];
var files = [];
var filesCount = 0;
var filesCountFail = 0;
let files = [];
let filesCount = 0;
let filesCountFail = 0;
// onLoad for FileReader API
var readerOnLoad = function(readEvent) {
let readerOnLoad = function(readEvent) {
// get file content
try{
@@ -404,13 +405,13 @@ define([
}
};
var handleDragOver = function(dragEvent) {
let handleDragOver = function(dragEvent) {
dragEvent.stopPropagation();
dragEvent.preventDefault();
dragEvent.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
};
var handleFileSelect = function(evt){
let handleFileSelect = function(evt){
evt.stopPropagation();
evt.preventDefault();
@@ -421,14 +422,14 @@ define([
files = evt.dataTransfer.files; // FileList object.
for (var file; !!(file = files[filesCount]); filesCount++){
var reader = new FileReader();
for (let file; !!(file = files[filesCount]); filesCount++){
let reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsText(file);
}
};
var dropZone = downloadTabElement.find('.' + config.dragDropElementClass);
let dropZone = downloadTabElement.find('.' + config.dragDropElementClass);
dropZone[0].addEventListener('dragover', handleDragOver, false);
dropZone[0].addEventListener('drop', handleFileSelect, false);
@@ -436,19 +437,19 @@ define([
downloadTabElement.find('#' + config.buttonImportId).on('click', function(e) {
importFormElement.validator('validate');
var validImportForm = importFormElement.isValidForm();
let validImportForm = importFormElement.isValidForm();
if(validImportForm){
importData = importFormElement.getFormValues();
importData.mapData = [];
var fileElement = downloadTabElement.find('#' + config.fieldImportId);
let fileElement = downloadTabElement.find('#' + config.fieldImportId);
files = fileElement[0].files;
filesCount = 0;
filesCountFail = 0;
for (var file; !!(file = files[filesCount]); filesCount++){
var reader = new FileReader();
for (let file; !!(file = files[filesCount]); filesCount++){
let reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsText(file);
}
@@ -462,9 +463,9 @@ define([
// events for tab change
mapInfoDialog.find('.navbar a').on('shown.bs.tab', function(e){
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
let selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
let selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
let selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
if($(e.target).attr('href') === '#' + config.dialogMapSettingsContainerId){
// "settings" tab
@@ -498,13 +499,13 @@ define([
* import new map(s) data
* @param importData
*/
var importMaps = function(importData){
let importMaps = function(importData){
var importForm = $('#' + config.dialogMapImportFormId);
let importForm = $('#' + config.dialogMapImportFormId);
importForm.hideFormMessage('all');
// lock dialog
var dialogContent = importForm.parents('.modal-content');
let dialogContent = importForm.parents('.modal-content');
dialogContent.showLoadingAnimation();
$.ajax({
@@ -525,7 +526,7 @@ define([
Util.showNotify({title: 'Import finished', text: 'Map(s) imported', type: 'success'});
}
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': importMap', text: reason, type: 'error'});
}).always(function() {
importForm.find('input, select').resetFormFields().trigger('change');
@@ -540,9 +541,9 @@ define([
*/
$.fn.setExportMapData = function(mapData){
var fieldExport = $('#' + config.fieldExportId);
var filename = '';
var mapDataEncoded = '';
let fieldExport = $('#' + config.fieldExportId);
let filename = '';
let mapDataEncoded = '';
if(fieldExport.length){
filename = fieldExport.val();
@@ -553,7 +554,7 @@ define([
}
return this.each(function(){
var exportButton = $(this);
let exportButton = $(this);
exportButton.attr('href', 'data:' + mapDataEncoded);
exportButton.attr('download', filename + '.json');
});
@@ -564,11 +565,11 @@ define([
* init select2 fields within the settings dialog
* @param mapInfoDialog
*/
var initSettingsSelectFields = function(mapInfoDialog){
let initSettingsSelectFields = function(mapInfoDialog){
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
let selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
let selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
let selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
// init character select live search
selectElementCharacter.initAccessSelect({
@@ -595,12 +596,11 @@ define([
*/
$.fn.showDeleteMapDialog = function(mapData){
var mapName = mapData.config.name;
let mapName = mapData.config.name;
var mapDeleteDialog = bootbox.confirm('Delete map "' + mapName + '"?', function(result){
let mapDeleteDialog = bootbox.confirm('Delete map "' + mapName + '"?', function(result){
if(result){
var data = {mapData: mapData.config};
let data = {mapData: mapData.config};
$.ajax({
type: 'POST',
@@ -609,12 +609,12 @@ define([
dataType: 'json'
}).done(function(data){
Util.showNotify({title: 'Map deleted', text: 'Map: ' + mapName, type: 'success'});
$(mapDeleteDialog).modal('hide');
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + error;
let reason = status + ' ' + error;
Util.showNotify({title: jqXHR.status + ': deleteMap', text: reason, type: 'warning'});
$(document).setProgramStatus('problem');
}).always(function() {
$(mapDeleteDialog).modal('hide');
});
return false;

View File

@@ -11,7 +11,7 @@ define([
], function($, Init, Util, bootbox, MapUtil) {
'use strict';
var config = {
let config = {
// module info
moduleClass: 'pf-module', // class for each module
@@ -39,7 +39,7 @@ define([
};
// cache for system routes
var cache = {
let cache = {
systemRoutes: {} // jump information between solar systems
};
@@ -48,17 +48,17 @@ define([
* @param context
* @param routesData
*/
var callbackAddRouteRow = function(context, routesData){
let callbackAddRouteRow = function(context, routesData){
if(routesData.length > 0){
for(var i = 0; i < routesData.length; i++){
var routeData = routesData[i];
for(let i = 0; i < routesData.length; i++){
let routeData = routesData[i];
// format routeData
var rowData = formatRouteData(routeData);
let rowData = formatRouteData(routeData);
if(rowData.route){
var cacheKey = routeData.systemFromData.name.toLowerCase() +
let cacheKey = routeData.systemFromData.name.toLowerCase() +
'_' + routeData.systemToData.name.toLowerCase();
// update route cache
@@ -67,7 +67,7 @@ define([
updated: Util.getServerTime().getTime() / 1000
};
var rowElement = addRow(context, rowData);
let rowElement = addRow(context, rowData);
rowElement.initTooltips({
container: 'body'
@@ -86,15 +86,15 @@ define([
* @param rowData
* @returns {*}
*/
var addRow = function(context, rowData){
var dataTable = context.dataTable;
var rowElement = null;
var row = null;
var animationStatus = 'changed';
let addRow = function(context, rowData){
let dataTable = context.dataTable;
let rowElement = null;
let row = null;
let animationStatus = 'changed';
// search for an existing row (e.g. on mass "table refresh" [all routes])
// get rowIndex where column 1 (equals to "systemToData.name") matches rowData.systemToData.name
var indexes = dataTable.rows().eq(0).filter( function (rowIdx) {
let indexes = dataTable.rows().eq(0).filter( function (rowIdx) {
return (dataTable.cell(rowIdx, 1 ).data().name === rowData.systemToData.name);
});
@@ -122,17 +122,43 @@ define([
return rowElement;
};
/**
* requests route data from eveCentral API and execute callback
* @param requestData
* @param context
* @param callback
*/
let getRouteData = function(requestData, context, callback){
context.moduleElement.showLoadingAnimation();
$.ajax({
url: Init.path.searchRoute,
type: 'POST',
dataType: 'json',
data: requestData,
context: context
}).done(function(routesData){
this.moduleElement.hideLoadingAnimation();
// execute callback
callback(this, routesData.routesData);
});
};
/**
* update complete routes table (refresh all)
* @param moduleElement
* @param dataTable
*/
var updateRoutesTable = function(moduleElement, dataTable){
var context = {
let updateRoutesTable = function(moduleElement, dataTable){
let context = {
moduleElement: moduleElement,
dataTable: dataTable
};
var routeData = [];
let routeData = [];
dataTable.rows().every( function() {
routeData.push( getRouteRequestDataFromRowData( this.data() ));
@@ -146,7 +172,7 @@ define([
* @param {Object} rowData
* @returns {Object}
*/
var getRouteRequestDataFromRowData = function(rowData){
let getRouteRequestDataFromRowData = function(rowData){
return {
mapIds: (rowData.hasOwnProperty('mapIds')) ? rowData.mapIds : [],
systemFromData: (rowData.hasOwnProperty('systemFromData')) ? rowData.systemFromData : {},
@@ -157,7 +183,8 @@ define([
wormholes: (rowData.hasOwnProperty('wormholes')) ? rowData.wormholes | 0 : 1,
wormholesReduced: (rowData.hasOwnProperty('wormholesReduced')) ? rowData.wormholesReduced | 0 : 1,
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
safer: (rowData.hasOwnProperty('safer')) ? rowData.safer.value | 0 : 0
};
};
@@ -165,12 +192,12 @@ define([
* show route dialog. User can search for systems and jump-info for each system is added to a data table
* @param dialogData
*/
var showFindRouteDialog = function(dialogData){
let showFindRouteDialog = function(dialogData){
var mapSelectOptions = [];
var currentMapData = Util.getCurrentMapData();
let mapSelectOptions = [];
let currentMapData = Util.getCurrentMapData();
if(currentMapData !== false){
for(var i = 0; i < currentMapData.length; i++){
for(let i = 0; i < currentMapData.length; i++){
mapSelectOptions.push({
id: currentMapData[i].config.id,
name: currentMapData[i].config.name,
@@ -178,7 +205,7 @@ define([
});
}
}
var data = {
let data = {
id: config.routeDialogId,
selectClass: config.systemDialogSelectClass,
mapSelectId: config.mapSelectId,
@@ -188,9 +215,9 @@ define([
requirejs(['text!templates/dialog/route.html', 'mustache'], function(template, Mustache) {
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var findRouteDialog = bootbox.dialog({
let findRouteDialog = bootbox.dialog({
title: 'Route finder',
message: content,
show: false,
@@ -206,15 +233,15 @@ define([
// add new route to route table
// get form Values
var form = $('#' + config.routeDialogId).find('form');
let form = $('#' + config.routeDialogId).find('form');
var routeDialogData = $(form).getFormValues();
let routeDialogData = $(form).getFormValues();
// validate form
form.validator('validate');
// check whether the form is valid
var formValid = form.isValidForm();
let formValid = form.isValidForm();
if(formValid === false){
// don't close dialog
@@ -222,18 +249,18 @@ define([
}
// get all system data from select2
var systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
let systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
if(
systemSelectData &&
systemSelectData.length === 1
){
var context = {
let context = {
moduleElement: dialogData.moduleElement,
dataTable: dialogData.dataTable
};
var requestData = {
let requestData = {
routeData: [{
mapIds: routeDialogData.mapIds,
systemFromData: dialogData.systemFromData,
@@ -264,7 +291,7 @@ define([
setDialogObserver( $(this) );
// init map select ----------------------------------------------------------------
var mapSelect = $(this).find('#' + config.mapSelectId);
let mapSelect = $(this).find('#' + config.mapSelectId);
mapSelect.initMapSelect();
});
@@ -273,7 +300,7 @@ define([
// init system select live search ------------------------------------------------
// -> add some delay until modal transition has finished
var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'name'});
});
@@ -282,6 +309,69 @@ define([
});
};
/**
* draw route table
* @param mapId
* @param moduleElement
* @param systemFromData
* @param routesTable
* @param systemsTo
*/
let drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
let requestRouteData = [];
let currentTimestamp = Util.getServerTime().getTime();
// Skip some routes from search
// -> this should help to throttle requests (heavy CPU load for route calculation)
let defaultRoutesCount = Init.routeSearch.defaultCount;
for(let i = 0; i < systemsTo.length; i++){
let systemToData = systemsTo[i];
if(systemFromData.name !== systemToData.name){
let cacheKey = 'route_' + mapId + '_' + systemFromData.name.toUpperCase() + '_' + systemToData.name.toUpperCase();
if(
cache.systemRoutes.hasOwnProperty(cacheKey) &&
Math.round(
( currentTimestamp - (new Date( cache.systemRoutes[cacheKey].updated * 1000).getTime())) / 1000
) <= config.routeCacheTTL
){
// route data is cached (client side)
let context = {
dataTable: routesTable
};
addRow(context, cache.systemRoutes[cacheKey].data);
}else{
// get route data
let searchData = {
mapIds: [mapId],
systemFromData: systemFromData,
systemToData: systemToData,
skipSearch: requestRouteData.length >= defaultRoutesCount
};
requestRouteData.push( getRouteRequestDataFromRowData( searchData ));
}
}
}
// check if routes data is not cached and is requested
if(requestRouteData.length > 0){
let contextData = {
moduleElement: moduleElement,
dataTable: routesTable
};
let requestData = {
routeData: requestRouteData
};
getRouteData(requestData, contextData, callbackAddRouteRow);
}
};
/**
* show route settings dialog
* @param dialogData
@@ -289,12 +379,12 @@ define([
* @param systemFromData
* @param routesTable
*/
var showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
let showSettingsDialog = function(dialogData, moduleElement, systemFromData, routesTable){
var promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
let promiseStore = MapUtil.getLocaleData('map', dialogData.mapId);
promiseStore.then(function(dataStore) {
// selected systems (if already stored)
var systemSelectOptions = [];
let systemSelectOptions = [];
if(
dataStore &&
dataStore.routes
@@ -303,9 +393,9 @@ define([
}
// max count of "default" target systems
var maxSelectionLength = Init.routeSearch.maxDefaultCount;
let maxSelectionLength = Init.routeSearch.maxDefaultCount;
var data = {
let data = {
id: config.routeSettingsDialogId,
selectClass: config.systemDialogSelectClass,
systemSelectOptions: systemSelectOptions,
@@ -313,9 +403,9 @@ define([
};
requirejs(['text!templates/dialog/route_settings.html', 'mustache'], function(template, Mustache) {
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
var settingsDialog = bootbox.dialog({
let settingsDialog = bootbox.dialog({
title: 'Route settings',
message: content,
show: false,
@@ -328,10 +418,10 @@ define([
label: '<i class="fa fa-fw fa-check"></i>&nbsp;save',
className: 'btn-success',
callback: function () {
var form = this.find('form');
let form = this.find('form');
// get all system data from select2
var systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
var systemsTo = [];
let systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
let systemsTo = [];
if( systemSelectData.length > 0 ){
systemsTo = formSystemSelectData(systemSelectData);
@@ -353,7 +443,7 @@ define([
// init default system select -----------------------------------------------------
// -> add some delay until modal transition has finished
var systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'name', maxSelectionLength: maxSelectionLength});
});
@@ -368,10 +458,10 @@ define([
* @param {Array} data
* @returns {Array}
*/
var formSystemSelectData = function(data){
var formattedData = [];
let formSystemSelectData = function(data){
let formattedData = [];
for(let i = 0; i < data.length; i++){
var tmpData = data[i];
let tmpData = data[i];
formattedData.push({
name: tmpData.id,
@@ -386,21 +476,21 @@ define([
* set event observer for route finder dialog
* @param routeDialog
*/
var setDialogObserver = function(routeDialog){
var wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
var wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
var wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
var wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
let setDialogObserver = function(routeDialog){
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
// store current "checked" state for each box ---------------------------------------------
var storeCheckboxStatus = function(){
let storeCheckboxStatus = function(){
wormholeReducedCheckbox.data('selectState', wormholeReducedCheckbox.prop('checked'));
wormholeCriticalCheckbox.data('selectState', wormholeCriticalCheckbox.prop('checked'));
wormholeEolCheckbox.data('selectState', wormholeEolCheckbox.prop('checked'));
};
// on wormhole checkbox change ------------------------------------------------------------
var onWormholeCheckboxChange = function(){
let onWormholeCheckboxChange = function(){
if( $(this).is(':checked') ){
wormholeReducedCheckbox.prop('disabled', false);
@@ -429,37 +519,12 @@ define([
onWormholeCheckboxChange();
};
/**
* requests route data from eveCentral API and execute callback
* @param requestData
* @param context
* @param callback
*/
var getRouteData = function(requestData, context, callback){
context.moduleElement.showLoadingAnimation();
$.ajax({
url: Init.path.searchRoute,
type: 'POST',
dataType: 'json',
data: requestData,
context: context
}).done(function(routesData){
this.moduleElement.hideLoadingAnimation();
// execute callback
callback(this, routesData.routesData);
});
};
/**
* format route data from API request into dataTable row format
* @param routeData
* @returns {{}}
*/
var formatRouteData = function(routeData){
let formatRouteData = function(routeData){
/**
* get status icon for route
@@ -487,14 +552,18 @@ define([
// 0: not found
// 1: round (OK)
// 2: not searched
var routeStatus = routeData.skipSearch ? 2 : 0;
let routeStatus = routeData.skipSearch ? 2 : 0;
var reloadButton = '<i class="fa ' + ['fa-refresh'].join(' ') + '"></i>';
var searchButton = '<i class="fa ' + ['fa-search-plus '].join(' ') + '"></i>';
var deleteButton = '<i class="fa ' + ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
// button class for "safer" routes
let saferButtonClass = routeData.safer ? 'txt-color-success' : '';
let saferButton = '<i class="fa ' + ['fa-shield', 'txt-color', saferButtonClass].join(' ') + '"></i>';
let reloadButton = '<i class="fa ' + ['fa-refresh'].join(' ') + '"></i>';
let searchButton = '<i class="fa ' + ['fa-search-plus '].join(' ') + '"></i>';
let deleteButton = '<i class="fa ' + ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ') + '"></i>';
// default row data (e.g. no route found)
var tableRowData = {
let tableRowData = {
systemFromData: routeData.systemFromData,
systemToData: routeData.systemToData,
jumps: {
@@ -512,6 +581,10 @@ define([
wormholesReduced: routeData.wormholesReduced,
wormholesCritical: routeData.wormholesCritical,
wormholesEOL: routeData.wormholesEOL,
safer: {
value: routeData.safer,
button: saferButton
},
reload: {
button: routeData.skipSearch ? searchButton : reloadButton
},
@@ -530,14 +603,14 @@ define([
routeStatus = 1;
// add route Data
var jumpData = [];
var avgSecTemp = 0;
let jumpData = [];
let avgSecTemp = 0;
// loop all systems on this route
for(var i = 0; i < routeData.route.length; i++){
for(let i = 0; i < routeData.route.length; i++){
let routeNodeData = routeData.route[i];
// format system name (camelCase)
let systemName = routeNodeData.system.charAt(0).toUpperCase() + routeNodeData.system.slice(1).toLowerCase();
// format system name
let systemName = routeNodeData.system;
let systemSec = Number(routeNodeData.security).toFixed(1).toString();
let tempSystemSec = systemSec;
@@ -565,14 +638,14 @@ define([
}
}
var avgSec = ( avgSecTemp / (routeData.route.length - 1)).toFixed(2);
var avgSecForClass = Number(avgSec).toFixed(1);
let avgSec = ( avgSecTemp / (routeData.route.length - 1)).toFixed(2);
let avgSecForClass = Number(avgSec).toFixed(1);
if(avgSecForClass <= 0){
avgSecForClass = '0.0';
}
var avgSecClass = config.systemSecurityClassPrefix + avgSecForClass.toString().replace('.', '-');
let avgSecClass = config.systemSecurityClassPrefix + avgSecForClass.toString().replace('.', '-');
tableRowData.jumps = {
value: routeData.routeJumps,
@@ -599,15 +672,15 @@ define([
* get the route finder moduleElement
* @returns {*}
*/
var getModule = function(){
let getModule = function(){
// create new module container
var moduleElement = $('<div>', {
let moduleElement = $('<div>', {
class: [config.moduleClass, config.systemRouteModuleClass].join(' ')
});
// headline toolbar icons
var headlineToolbar = $('<h5>', {
let headlineToolbar = $('<h5>', {
class: 'pull-right'
}).append(
$('<i>', {
@@ -627,7 +700,7 @@ define([
moduleElement.append(headlineToolbar);
// headline
var headline = $('<h5>', {
let headline = $('<h5>', {
class: 'pull-left',
text: 'Routes'
});
@@ -635,14 +708,14 @@ define([
moduleElement.append(headline);
// crate new route table
var table = $('<table>', {
let table = $('<table>', {
class: ['compact', 'stripe', 'order-column', 'row-border', config.systemInfoRoutesTableClass].join(' ')
});
moduleElement.append( $(table) );
// init empty table
var routesTable = table.DataTable( {
let routesTable = table.DataTable( {
paging: false,
ordering: true,
order: [[ 2, 'asc' ], [ 0, 'asc' ]],
@@ -711,41 +784,35 @@ define([
data: 'route'
},{
targets: 5,
title: '',
title: '<i title="search safer route (HS)" data-toggle="tooltip" class="fa fa-shield text-right"></i>',
orderable: false,
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'reload',
data: 'safer',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
var tempTableApi = this.api();
let tempTableApi = this.api();
$(cell).on('click', function(e) {
// get current row data (important!)
// -> "rowData" param is not current state, values are "on createCell()" state
rowData = tempTableApi.row( $(cell).parents('tr')).data();
let routeData = getRouteRequestDataFromRowData( rowData );
var context = {
// overwrite some params
routeData.skipSearch = 0;
routeData.safer = 1 - routeData.safer; // toggle
let context = {
moduleElement: moduleElement,
dataTable: tempTableApi
};
var requestData = {
routeData: [{
mapIds: rowData.mapIds,
systemFromData: rowData.systemFromData,
systemToData: rowData.systemToData,
skipSearch: 0,
stargates: rowData.stargates ? 1 : 0,
jumpbridges: rowData.jumpbridges ? 1 : 0,
wormholes: rowData.wormholes ? 1 : 0,
wormholesReduced: rowData.wormholesReduced ? 1 : 0,
wormholesCritical: rowData.wormholesCritical ? 1 : 0,
wormholesEOL: rowData.wormholesEOL ? 1 : 0
}]
let requestData = {
routeData: [routeData]
};
getRouteData(requestData, context, callbackAddRouteRow);
@@ -758,14 +825,49 @@ define([
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'reload',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
let tempTableApi = this.api();
$(cell).on('click', function(e) {
// get current row data (important!)
// -> "rowData" param is not current state, values are "on createCell()" state
rowData = tempTableApi.row( $(cell).parents('tr')).data();
let routeData = getRouteRequestDataFromRowData( rowData );
// overwrite some params
routeData.skipSearch = 0;
let context = {
moduleElement: moduleElement,
dataTable: tempTableApi
};
let requestData = {
routeData: [routeData]
};
getRouteData(requestData, context, callbackAddRouteRow);
});
}
},{
targets: 7,
title: '',
orderable: false,
searchable: false,
width: '10px',
class: ['text-center', config.dataTableActionCellClass].join(' '),
data: 'clear',
render: {
_: 'button'
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
var tempTableElement = this;
let tempTableElement = this;
var confirmationSettings = {
let confirmationSettings = {
container: 'body',
placement: 'left',
btnCancelClass: 'btn btn-sm btn-default',
@@ -776,7 +878,7 @@ define([
btnOkLabel: 'delete',
btnOkIcon: 'fa fa-fw fa-close',
onConfirm : function(e, target){
var deleteRowElement = $(cell).parents('tr');
let deleteRowElement = $(cell).parents('tr');
tempTableElement.api().rows(deleteRowElement).remove().draw();
}
};
@@ -788,14 +890,14 @@ define([
],
drawCallback: function(settings){
var animationRows = this.api().rows().nodes().to$().filter(function() {
let animationRows = this.api().rows().nodes().to$().filter(function() {
return (
$(this).data('animationStatus') ||
$(this).data('animationTimer')
);
});
for(var i = 0; i < animationRows.length; i++){
for(let i = 0; i < animationRows.length; i++){
$(animationRows[i]).pulseTableRow($(animationRows[i]).data('animationStatus'));
$(animationRows[i]).removeData('animationStatus');
}
@@ -805,7 +907,7 @@ define([
});
// init tooltips for this module
var tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
let tooltipElements = moduleElement.find('[data-toggle="tooltip"]');
tooltipElements.tooltip({
container: 'body'
});
@@ -819,19 +921,19 @@ define([
* @param options
*/
$.fn.initSystemPopover = function(options){
var elements = $(this);
var eventNamespace = 'hideSystemPopup';
var systemToData = options.systemToData;
let elements = $(this);
let eventNamespace = 'hideSystemPopup';
let systemToData = options.systemToData;
requirejs(['text!templates/tooltip/system_popover.html', 'mustache'], function (template, Mustache) {
var data = {
let data = {
systemToData: systemToData
};
var content = Mustache.render(template, data);
let content = Mustache.render(template, data);
elements.each(function() {
var element = $(this);
let element = $(this);
// destroy "popover" and remove "click" event for animation
element.popover('destroy').off();
@@ -859,11 +961,11 @@ define([
// set link observer "on shown" event
elements.on('shown.bs.popover', function () {
var popoverRoot = $(this);
let popoverRoot = $(this);
popoverRoot.data('bs.popover').tip().find('a').on('click', function(){
// hint: "data" attributes should be in lower case!
var systemData = {
let systemData = {
name: $(this).data('name'),
systemId: $(this).data('systemid')
};
@@ -883,16 +985,16 @@ define([
* @param mapId
* @param systemData
*/
var initModule = function(moduleElement, mapId, systemData){
let initModule = function(moduleElement, mapId, systemData){
var systemFromData = {
let systemFromData = {
name: systemData.name,
systemId: systemData.systemId
};
var routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
let routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
var routesTable = routesTableElement.DataTable();
let routesTable = routesTableElement.DataTable();
// init refresh routes --------------------------------------------------------------------
moduleElement.find('.' + config.systemModuleHeadlineIconRefresh).on('click', function(e){
@@ -907,7 +1009,7 @@ define([
// max routes limit reached -> show warning
Util.showNotify({title: 'Route limit reached', text: 'Serch is limited by ' + maxRouteSearchLimit, type: 'warning'});
}else{
var dialogData = {
let dialogData = {
moduleElement: moduleElement,
mapId: mapId,
systemFromData: systemFromData,
@@ -922,7 +1024,7 @@ define([
// init settings dialog -------------------------------------------------------------------
moduleElement.find('.' + config.systemModuleHeadlineIconSettings).on('click', function(e){
var dialogData = {
let dialogData = {
mapId: mapId
};
@@ -930,10 +1032,10 @@ define([
});
// fill routesTable with data -------------------------------------------------------------
var promiseStore = MapUtil.getLocaleData('map', mapId);
let promiseStore = MapUtil.getLocaleData('map', mapId);
promiseStore.then(function(dataStore) {
// selected systems (if already stored)
var systemsTo = [{
let systemsTo = [{
name: 'Jita',
systemId: 30000142
}];
@@ -950,69 +1052,6 @@ define([
};
/**
* draw route table
* @param mapId
* @param moduleElement
* @param systemFromData
* @param routesTable
* @param systemsTo
*/
var drawRouteTable = function(mapId, moduleElement, systemFromData, routesTable, systemsTo){
var requestRouteData = [];
var currentTimestamp = Util.getServerTime().getTime();
// Skip some routes from search
// -> this should help to throttle requests (heavy CPU load for route calculation)
var defaultRoutesCount = Init.routeSearch.defaultCount;
for(var i = 0; i < systemsTo.length; i++){
var systemToData = systemsTo[i];
if(systemFromData.name !== systemToData.name){
var cacheKey = 'route_' + mapId + '_' + systemFromData.name.toUpperCase() + '_' + systemToData.name.toUpperCase();
if(
cache.systemRoutes.hasOwnProperty(cacheKey) &&
Math.round(
( currentTimestamp - (new Date( cache.systemRoutes[cacheKey].updated * 1000).getTime())) / 1000
) <= config.routeCacheTTL
){
// route data is cached (client side)
var context = {
dataTable: routesTable
};
addRow(context, cache.systemRoutes[cacheKey].data);
}else{
// get route data
var searchData = {
mapIds: [mapId],
systemFromData: systemFromData,
systemToData: systemToData,
skipSearch: requestRouteData.length >= defaultRoutesCount
};
requestRouteData.push( getRouteRequestDataFromRowData( searchData ));
}
}
}
// check if routes data is not cached and is requested
if(requestRouteData.length > 0){
var contextData = {
moduleElement: moduleElement,
dataTable: routesTable
};
var requestData = {
routeData: requestRouteData
};
getRouteData(requestData, contextData, callbackAddRouteRow);
}
};
/**
* updates an dom element with the system route module
* @param mapId
@@ -1020,10 +1059,10 @@ define([
*/
$.fn.drawSystemRouteModule = function(mapId, systemData){
var parentElement = $(this);
let parentElement = $(this);
// show route module
var showModule = function(moduleElement){
let showModule = function(moduleElement){
if(moduleElement){
moduleElement.css({ opacity: 0 });
parentElement.append(moduleElement);
@@ -1039,7 +1078,7 @@ define([
};
// check if module already exists
var moduleElement = parentElement.find('.' + config.systemRouteModuleClass);
let moduleElement = parentElement.find('.' + config.systemRouteModuleClass);
if(moduleElement.length > 0){
moduleElement.velocity('transition.slideDownOut', {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
'use strict';
// "fake" window object will contain "MsgWorker" after import
let window = {}; // jshint ignore:line
// import "MsgWorker" class
self.importScripts( self.name ); // jshint ignore:line
let MsgWorker = window.MsgWorker;
let socket = null;
let ports = [];
let characterPorts = [];
// init "WebSocket" connection ========================================================================================
let initSocket = (uri) => {
let MsgWorkerOpen = new MsgWorker('ws:open');
if(socket === null){
socket = new WebSocket(uri);
// "WebSocket" open -----------------------------------------------------------------------
socket.onopen = (e) => {
MsgWorkerOpen.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerOpen);
};
// "WebSocket message ---------------------------------------------------------------------
socket.onmessage = (e) => {
let response = JSON.parse(e.data);
let MsgWorkerSend = new MsgWorker('ws:send');
MsgWorkerSend.task( response.task );
MsgWorkerSend.meta({
readyState: this.readyState,
characterIds: response.characterIds
});
MsgWorkerSend.data( response.load );
broadcastPorts(MsgWorkerSend);
};
// "WebSocket" close ----------------------------------------------------------------------
socket.onclose = (closeEvent) => {
let MsgWorkerClosed = new MsgWorker('ws:closed');
MsgWorkerClosed.meta({
readyState: socket.readyState,
code: closeEvent.code,
reason: closeEvent.reason,
wasClean: closeEvent.wasClean
});
broadcastPorts(MsgWorkerClosed);
socket = null; // reset WebSocket
};
// "WebSocket" error ----------------------------------------------------------------------
socket.onerror = (e) => {
let MsgWorkerError = new MsgWorker('ws:error');
MsgWorkerError.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerError);
};
}else{
// socket still open
MsgWorkerOpen.meta({
readyState: socket.readyState
});
sendToCurrentPort(MsgWorkerOpen);
}
};
// send message to port(s) ============================================================================================
let sendToCurrentPort = (load) => {
ports[ports.length - 1].postMessage(load);
};
let broadcastPorts = (load) => {
// default: sent to all ports
let sentToPorts = ports;
// check if send() is limited to some ports
let meta = load.meta();
if(
meta &&
meta.characterIds &&
meta.characterIds !== 'undefined' &&
meta.characterIds instanceof Array
){
// ... get ports for characterIds
sentToPorts = getPortsByCharacterIds(meta.characterIds);
}
for (let i = 0; i < sentToPorts.length; i++) {
sentToPorts[i].postMessage(load);
}
};
// port functions =====================================================================================================
let addPort = (port, characterId) => {
characterId = parseInt(characterId);
if(characterId > 0){
characterPorts.push({
characterId: characterId,
port: port
});
}else{
ports.push(port);
}
};
let getPortsByCharacterIds = (characterIds) => {
let ports = [];
for(let i = 0; i < characterPorts.length; i++){
for(let j = 0; j < characterIds.length; j++){
if(characterPorts[i].characterId === characterIds[j]){
ports.push(characterPorts[i].port);
}
}
}
return ports;
};
// "SharedWorker" connection ==========================================================================================
self.addEventListener('connect', (event) => { // jshint ignore:line
let port = event.ports[0];
addPort(port);
port.addEventListener('message', (e) => {
let MsgWorkerMessage = e.data;
Object.setPrototypeOf(MsgWorkerMessage, MsgWorker.prototype);
switch(MsgWorkerMessage.command){
case 'ws:init':
let data = MsgWorkerMessage.data();
// add character specific port (for broadcast) to individual ports (tabs)
addPort(port, data.characterId);
initSocket(data.uri);
break;
case 'ws:send':
let MsgSocket = {
task: MsgWorkerMessage.task(),
load: MsgWorkerMessage.data()
};
socket.send(JSON.stringify(MsgSocket));
break;
case 'ws:close':
// closeSocket();
break;
}
}, false);
port.start();
}, false);

View File

@@ -0,0 +1,55 @@
window.MsgWorker = class MessageWorker {
constructor(cmd){
/**
* "command" type (identifies this message)
*/
this.cmd = cmd;
/**
* "task" what should be done with this message
* @type {string}
*/
this.msgTask = '';
/**
* "message" meta data (e.g. error/close data from WebSocket
* @type {null}
*/
this.msgMeta = null;
/**
* "message" body (load)
* @type {null}
*/
this.msgBody = null;
}
get command(){
return this.cmd;
}
task(task) {
if(task){
this.msgTask = task;
}
return this.msgTask;
}
meta(metaData) {
if(metaData){
this.msgMeta = metaData;
}
return this.msgMeta;
}
data(data) {
if(data){
this.msgBody = data;
}
return this.msgBody;
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long