- Improved "signature type" map overlays on "connection endpoints", closed #725
- Upgraded "[localForage](https://localforage.github.io/localForage)", JS lib `v1.4.2` → `v1.7.3` - Upgraded "[Mustache](http://mustache.github.io)", JS lib `v1.0.0` → `v3.0.1`
This commit is contained in:
@@ -14,7 +14,7 @@ NAME = Pathfinder
|
||||
; e.g. public/js/vX.X.X/app.js
|
||||
; Syntax: String (current version)
|
||||
; Default: v1.5.0
|
||||
VERSION = v1.5.1
|
||||
VERSION = v1.5.2
|
||||
|
||||
; Contact information [optional]
|
||||
; Shown on 'licence', 'contact' page.
|
||||
|
||||
@@ -22,9 +22,6 @@ PCRE_VERSION = 8.02
|
||||
; Redis extension (optional), required if you want to use Redis as caching Engine (recommended)
|
||||
REDIS = 3.0.0
|
||||
|
||||
; ZeroMQ (ØMQ) extension (optional) required for WebSocket Server extension (recommended)
|
||||
ZMQ = 1.1.3
|
||||
|
||||
; Event extension (optional) for WebSocket configuration. Better performance
|
||||
; https://pecl.php.net/package/event
|
||||
EVENT = 2.3.0
|
||||
@@ -48,9 +45,6 @@ MAX_INPUT_VARS = 3000
|
||||
; Formatted HTML StackTraces
|
||||
HTML_ERRORS = 0
|
||||
|
||||
[REQUIREMENTS.LIBS]
|
||||
ZMQ = 4.1.3
|
||||
|
||||
[REQUIREMENTS.MYSQL]
|
||||
; min MySQL Version
|
||||
; newer "deviation" of MySQL like "MariaDB" > 10.1 are recommended
|
||||
|
||||
@@ -28,11 +28,11 @@ requirejs.config({
|
||||
jquery: 'lib/jquery-3.3.1.min', // v3.3.1 jQuery
|
||||
bootstrap: 'lib/bootstrap.min', // v3.3.0 Bootstrap js code - http://getbootstrap.com/javascript
|
||||
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
|
||||
mustache: 'lib/mustache.min', // v3.0.1 Javascript template engine - http://mustache.github.io
|
||||
localForage: 'lib/localforage.min', // v1.7.3 localStorage library - https://localforage.github.io/localForage/
|
||||
velocity: 'lib/velocity.min', // v1.5.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
|
||||
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin https://www.adchsm.com/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
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
|
||||
|
||||
@@ -9,14 +9,14 @@ define([
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/contextmenu',
|
||||
'app/map/overlay',
|
||||
'app/map/system',
|
||||
'app/map/layout',
|
||||
'app/map/magnetizing',
|
||||
'app/map/scrollbar',
|
||||
'dragToSelect',
|
||||
'app/map/overlay',
|
||||
'app/map/local'
|
||||
], ($, Init, Util, bootbox, MapUtil, MapContextMenu, System, Layout, MagnetizerWrapper) => {
|
||||
], ($, Init, Util, bootbox, MapUtil, MapContextMenu, MapOverlay, System, Layout, MagnetizerWrapper) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -130,10 +130,10 @@ define([
|
||||
// -> we need BOTH endpoints of a connection -> index 0
|
||||
for(let endpoint of connectionInfo[0].endpoints){
|
||||
// check if there is a Label overlay
|
||||
let overlay = endpoint.getOverlay('pf-map-endpoint-overlay');
|
||||
let overlay = endpoint.getOverlay(MapOverlay.endpointOverlayId);
|
||||
if(overlay instanceof jsPlumb.Overlays.Label){
|
||||
let label = overlay.getParameter('label');
|
||||
overlay.setLocation(MapUtil.getLabelEndpointOverlayLocation(endpoint, label));
|
||||
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, label));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2469,6 +2469,25 @@ define([
|
||||
selector: '.' + config.systemHeadInfoClass + ' span[class^="pf-system-sec-"]'
|
||||
});
|
||||
|
||||
// toggle "fullSize" Endpoint overlays for system (signature information) -------------------------------------
|
||||
mapContainer.hoverIntent({
|
||||
over: function(e){
|
||||
for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlay.endpointOverlayId)){
|
||||
if(overlayInfo[0] instanceof jsPlumb.Overlays.Label){
|
||||
overlayInfo[0].fire('toggleSize', true);
|
||||
}
|
||||
}
|
||||
},
|
||||
out: function(e){
|
||||
for(let overlayInfo of map.selectEndpoints({element: this}).getOverlay(MapOverlay.endpointOverlayId)){
|
||||
if(overlayInfo[0] instanceof jsPlumb.Overlays.Label){
|
||||
overlayInfo[0].fire('toggleSize', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
selector: '.' + config.systemClass
|
||||
});
|
||||
|
||||
// catch events ===============================================================================================
|
||||
|
||||
// toggle global map option (e.g. "grid snap", "magnetization")
|
||||
|
||||
@@ -13,9 +13,6 @@ define([
|
||||
let config = {
|
||||
logTimerCount: 3, // map log timer in seconds
|
||||
|
||||
// map
|
||||
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
|
||||
|
||||
// map overlay positions
|
||||
mapOverlayClass: 'pf-map-overlay', // class for all map overlays
|
||||
mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
|
||||
@@ -60,6 +57,43 @@ define([
|
||||
return getMapObjectFromMapElement( mapElement );
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlay to endpoint with signature data
|
||||
* @param endpoint
|
||||
* @param labelData
|
||||
*/
|
||||
let addEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let label = labelData.labels.join(', ');
|
||||
let name = labelData.names.join(', ');
|
||||
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(label),
|
||||
id: config.endpointOverlayId,
|
||||
cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
|
||||
events: {
|
||||
toggleSize: function(fullSize){
|
||||
let signatureName = this.getParameter('signatureName');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureName){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureName + '</span>');
|
||||
this.setParameter('fullSize', true);
|
||||
}else if(this.getParameter('fullSize')){
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
|
||||
this.setParameter('fullSize', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
fullSize: false,
|
||||
label: label,
|
||||
signatureName: name
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlays to connections (signature based data)
|
||||
* @param connections
|
||||
@@ -68,54 +102,38 @@ define([
|
||||
let addConnectionsOverlay = (connections, connectionsData) => {
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
|
||||
/**
|
||||
* add label to endpoint
|
||||
* @param endpoint
|
||||
* @param label
|
||||
*/
|
||||
let addEndpointOverlay = (endpoint, label) => {
|
||||
label = label.join(', ');
|
||||
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: MapUtil.getEndpointOverlayContent(label),
|
||||
id: config.endpointOverlayId,
|
||||
cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getLabelEndpointOverlayLocation(endpoint, label),
|
||||
parameters: {
|
||||
label: label
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
// loop through all map connections (get from DOM)
|
||||
for(let connection of connections){
|
||||
let connectionId = connection.getParameter('connectionId');
|
||||
let sourceEndpoint = connection.endpoints[0];
|
||||
let targetEndpoint = connection.endpoints[1];
|
||||
|
||||
let signatureTypeNames = {
|
||||
sourceLabels: [],
|
||||
targetLabels: []
|
||||
let signatureTypeData = {
|
||||
source: {
|
||||
names: [],
|
||||
labels: []
|
||||
},
|
||||
target: {
|
||||
names: [],
|
||||
labels: []
|
||||
}
|
||||
};
|
||||
|
||||
// ... find matching connectionData (from Ajax)
|
||||
for(let connectionData of connectionsData){
|
||||
if(connectionData.id === connectionId){
|
||||
signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
// ... connection matched -> continue with next one
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let sourceLabel = signatureTypeNames.sourceLabels;
|
||||
let targetLabel = signatureTypeNames.targetLabels;
|
||||
|
||||
// add endpoint overlays ------------------------------------------------------
|
||||
addEndpointOverlay(sourceEndpoint, sourceLabel);
|
||||
addEndpointOverlay(targetEndpoint, targetLabel);
|
||||
addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
|
||||
let sourceLabel = signatureTypeData.source.labels;
|
||||
let targetLabel = signatureTypeData.target.labels;
|
||||
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ------------
|
||||
let overlayType = 'Diamond'; // not specified
|
||||
@@ -472,7 +490,7 @@ define([
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMapOverlay = function(overlayType){
|
||||
let mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
|
||||
let mapWrapperElement = $(this).parents('.' + MapUtil.config.mapWrapperClass);
|
||||
|
||||
let mapOverlay = null;
|
||||
switch(overlayType){
|
||||
@@ -744,4 +762,8 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
endpointOverlayId: config.endpointOverlayId
|
||||
};
|
||||
|
||||
});
|
||||
@@ -498,12 +498,18 @@ define([
|
||||
* -> data requires a signature bind to that connection
|
||||
* @param connection
|
||||
* @param connectionData
|
||||
* @returns {{sourceLabels: Array, targetLabels: Array}}
|
||||
* @returns {{source: {names: Array, labels: Array}, target: {names: Array, labels: Array}}}
|
||||
*/
|
||||
let getConnectionDataFromSignatures = (connection, connectionData) => {
|
||||
let signatureTypeNames = {
|
||||
sourceLabels: [],
|
||||
targetLabels: []
|
||||
let signatureTypeData = {
|
||||
source: {
|
||||
names: [],
|
||||
labels: []
|
||||
},
|
||||
target: {
|
||||
names: [],
|
||||
labels: []
|
||||
}
|
||||
};
|
||||
|
||||
if(
|
||||
@@ -530,11 +536,11 @@ define([
|
||||
|
||||
if(signatureData.system.id === sourceId){
|
||||
// relates to "source" endpoint
|
||||
tmpSystemType = 'sourceLabels';
|
||||
tmpSystemType = 'source';
|
||||
tmpSystem = sourceSystem;
|
||||
}else if(signatureData.system.id === targetId){
|
||||
// relates to "target" endpoint
|
||||
tmpSystemType = 'targetLabels';
|
||||
tmpSystemType = 'target';
|
||||
tmpSystem = targetSystem;
|
||||
}
|
||||
|
||||
@@ -544,18 +550,19 @@ define([
|
||||
let availableSigTypeNames = SystemSignatures.getAllSignatureNamesBySystem(tmpSystem, 5);
|
||||
let flattenSigTypeNames = Util.flattenXEditableSelectArray(availableSigTypeNames);
|
||||
|
||||
if( flattenSigTypeNames.hasOwnProperty(signatureData.typeId) ){
|
||||
if(flattenSigTypeNames.hasOwnProperty(signatureData.typeId)){
|
||||
let label = flattenSigTypeNames[signatureData.typeId];
|
||||
// shorten label, just take the in game name
|
||||
label = label.substr(0, label.indexOf(' '));
|
||||
signatureTypeNames[tmpSystemType].push(label);
|
||||
signatureTypeData[tmpSystemType].names.push(signatureData.name);
|
||||
signatureTypeData[tmpSystemType].labels.push(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signatureTypeNames;
|
||||
return signatureTypeData;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -566,7 +573,7 @@ define([
|
||||
* @param label
|
||||
* @returns {number[]}
|
||||
*/
|
||||
let getLabelEndpointOverlayLocation = (endpoint, label) => {
|
||||
let getEndpointOverlaySignatureLocation = (endpoint, label) => {
|
||||
let chars = label.length ? label.length : 2;
|
||||
let xTop = chars === 2 ? +0.05 : chars <= 4 ? -0.75 : 3;
|
||||
let xLeft = chars === 2 ? -1.10 : chars <= 4 ? -2.75 : 3;
|
||||
@@ -589,7 +596,7 @@ define([
|
||||
* @param label
|
||||
* @returns {string}
|
||||
*/
|
||||
let getEndpointOverlayContent = label => {
|
||||
let formatEndpointOverlaySignatureLabel = label => {
|
||||
let colorClass = 'txt-color-grayLighter';
|
||||
|
||||
if(label.length > 0){
|
||||
@@ -1825,8 +1832,8 @@ define([
|
||||
getDataByConnections: getDataByConnections,
|
||||
deleteConnections: deleteConnections,
|
||||
getConnectionDataFromSignatures: getConnectionDataFromSignatures,
|
||||
getLabelEndpointOverlayLocation: getLabelEndpointOverlayLocation,
|
||||
getEndpointOverlayContent: getEndpointOverlayContent,
|
||||
getEndpointOverlaySignatureLocation: getEndpointOverlaySignatureLocation,
|
||||
formatEndpointOverlaySignatureLabel: formatEndpointOverlaySignatureLabel,
|
||||
getTabContentElementByMapElement: getTabContentElementByMapElement,
|
||||
hasActiveConnection: hasActiveConnection,
|
||||
filterMapByScopes: filterMapByScopes,
|
||||
|
||||
@@ -306,10 +306,10 @@ define([
|
||||
let connection = $().getConnectionById(data.mapId, data.connectionId);
|
||||
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
|
||||
let sourceLabel = signatureTypeNames.sourceLabels;
|
||||
let targetLabel = signatureTypeNames.targetLabels;
|
||||
sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel.join(', ')));
|
||||
targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel.join(', ')));
|
||||
let sourceLabel = signatureTypeNames.source.labels;
|
||||
let targetLabel = signatureTypeNames.target.labels;
|
||||
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabel.join(', ')));
|
||||
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabel.join(', ')));
|
||||
|
||||
// remove K162
|
||||
sourceLabel = sourceLabel.diff(['K162']);
|
||||
|
||||
8
js/lib/localforage.min.js
vendored
8
js/lib/localforage.min.js
vendored
File diff suppressed because one or more lines are too long
2
js/lib/mustache.min.js
vendored
2
js/lib/mustache.min.js
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
"use strict";var mainScriptPath=document.body.getAttribute("data-script"),jsBaseUrl=document.body.getAttribute("data-js-path");requirejs.config({baseUrl:"js",paths:{layout:"layout",conf:"app/conf",dialog:"app/ui/dialog",templates:"../../templates",img:"../../img",login:"./app/login",mappage:"./app/mappage",setup:"./app/setup",admin:"./app/admin",notification:"./app/notification",jquery:"lib/jquery-3.3.1.min",bootstrap:"lib/bootstrap.min",text:"lib/requirejs/text",mustache:"lib/mustache.min",localForage:"lib/localforage.min",velocity:"lib/velocity.min",velocityUI:"lib/velocity.ui.min",slidebars:"lib/slidebars",jsPlumb:"lib/dom.jsPlumb-1.7.6",farahey:"lib/farahey-0.5",customScrollbar:"lib/jquery.mCustomScrollbar.min",mousewheel:"lib/jquery.mousewheel.min",xEditable:"lib/bootstrap-editable.min",morris:"lib/morris.min",raphael:"lib/raphael-min",bootbox:"lib/bootbox.min",easyPieChart:"lib/jquery.easypiechart.min",peityInlineChart:"lib/jquery.peity.min",dragToSelect:"lib/jquery.dragToSelect",hoverIntent:"lib/jquery.hoverIntent.min",fullScreen:"lib/jquery.fullscreen.min",select2:"lib/select2.min",validator:"lib/validator.min",lazylinepainter:"lib/jquery.lazylinepainter-1.5.1.min",blueImpGallery:"lib/blueimp-gallery",blueImpGalleryHelper:"lib/blueimp-helper",blueImpGalleryBootstrap:"lib/bootstrap-image-gallery",bootstrapConfirmation:"lib/bootstrap-confirmation",bootstrapToggle:"lib/bootstrap-toggle.min",lazyload:"lib/jquery.lazyload.min",sortable:"lib/sortable.min","summernote.loader":"./app/summernote.loader",summernote:"lib/summernote/summernote.min",easePack:"lib/EasePack.min",tweenLite:"lib/TweenLite.min","datatables.loader":"./app/datatables.loader","datatables.net":"lib/datatables/DataTables-1.10.12/js/jquery.dataTables.min","datatables.net-buttons":"lib/datatables/Buttons-1.2.1/js/dataTables.buttons.min","datatables.net-buttons-html":"lib/datatables/Buttons-1.2.1/js/buttons.html5.min","datatables.net-responsive":"lib/datatables/Responsive-2.1.0/js/dataTables.responsive.min","datatables.net-select":"lib/datatables/Select-1.2.0/js/dataTables.select.min","datatables.plugins.render.ellipsis":"lib/datatables/plugins/render/ellipsis",pnotify:"lib/pnotify/pnotify","pnotify.buttons":"lib/pnotify/pnotify.buttons","pnotify.confirm":"lib/pnotify/pnotify.confirm","pnotify.nonblock":"lib/pnotify/pnotify.nonblock","pnotify.desktop":"lib/pnotify/pnotify.desktop","pnotify.history":"lib/pnotify/pnotify.history","pnotify.callbacks":"lib/pnotify/pnotify.callbacks","pnotify.reference":"lib/pnotify/pnotify.reference"},shim:{bootstrap:{deps:["jquery"]},farahey:{deps:["jsPlumb"]},velocity:{deps:["jquery"]},velocityUI:{deps:["velocity"]},slidebars:{deps:["jquery"]},customScrollbar:{deps:["jquery","mousewheel"]},"datatables.loader":{deps:["jquery"]},"datatables.net":{deps:["jquery"]},"datatables.net-buttons":{deps:["datatables.net"]},"datatables.net-buttons-html":{deps:["datatables.net-buttons"]},"datatables.net-responsive":{deps:["datatables.net"]},"datatables.net-select":{deps:["datatables.net"]},"datatables.plugins.render.ellipsis":{deps:["datatables.net"]},xEditable:{deps:["bootstrap"]},bootbox:{deps:["jquery","bootstrap"],exports:"bootbox"},morris:{deps:["jquery","raphael"],exports:"Morris",init:function(e,t){window.Raphael=t}},pnotify:{deps:["jquery"]},easyPieChart:{deps:["jquery"]},peityInlineChart:{deps:["jquery"]},dragToSelect:{deps:["jquery"]},hoverIntent:{deps:["jquery"]},fullScreen:{deps:["jquery"]},select2:{deps:["jquery","mousewheel"],exports:"Select2"},validator:{deps:["jquery","bootstrap"]},lazylinepainter:{deps:["jquery","bootstrap"]},blueImpGallery:{deps:["jquery"]},bootstrapConfirmation:{deps:["bootstrap"]},bootstrapToggle:{deps:["jquery"]},lazyload:{deps:["jquery"]},summernote:{deps:["jquery"]}}}),require.config({baseUrl:jsBaseUrl}),requirejs([mainScriptPath]);
|
||||
//# sourceMappingURL=app.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app.js"],"names":["mainScriptPath","document","body","getAttribute","jsBaseUrl","requirejs","config","baseUrl","paths","layout","conf","dialog","templates","img","login","mappage","setup","admin","notification","jquery","bootstrap","text","mustache","localForage","velocity","velocityUI","slidebars","jsPlumb","farahey","customScrollbar","mousewheel","xEditable","morris","raphael","bootbox","easyPieChart","peityInlineChart","dragToSelect","hoverIntent","fullScreen","select2","validator","lazylinepainter","blueImpGallery","blueImpGalleryHelper","blueImpGalleryBootstrap","bootstrapConfirmation","bootstrapToggle","lazyload","sortable","summernote.loader","summernote","easePack","tweenLite","datatables.loader","datatables.net","datatables.net-buttons","datatables.net-buttons-html","datatables.net-responsive","datatables.net-select","datatables.plugins.render.ellipsis","pnotify","pnotify.buttons","pnotify.confirm","pnotify.nonblock","pnotify.desktop","pnotify.history","pnotify.callbacks","pnotify.reference","shim","deps","exports","init","$","Raphael","window","require"],"mappings":"AAAA,aAGA,IAAIA,eAAiBC,SAASC,KAAKC,aAAa,eAI5CC,UAAYH,SAASC,KAAKC,aAAa,gBAG3CE,UAAUC,QACNC,QAAS,KAETC,OACIC,OAAQ,SACRC,KAAM,WACNC,OAAQ,gBACRC,UAAW,kBACXC,IAAK,YAGLC,MAAO,cACPC,QAAS,gBACTC,MAAO,cACPC,MAAO,cACPC,aAAc,qBAEdC,OAAQ,uBACRC,UAAW,oBACXC,KAAM,qBACNC,SAAU,mBACVC,YAAa,sBACbC,SAAU,mBACVC,WAAY,sBACZC,UAAW,gBACXC,QAAS,wBACTC,QAAS,kBACTC,gBAAiB,kCACjBC,WAAY,4BACZC,UAAW,6BACXC,OAAQ,iBACRC,QAAS,kBACTC,QAAS,kBACTC,aAAc,8BACdC,iBAAkB,uBAClBC,aAAc,0BACdC,YAAa,6BACbC,WAAY,4BACZC,QAAS,kBACTC,UAAW,oBACXC,gBAAiB,uCACjBC,eAAgB,sBAChBC,qBAAsB,qBACtBC,wBAAyB,8BACzBC,sBAAuB,6BACvBC,gBAAiB,2BACjBC,SAAU,0BACVC,SAAU,mBAEVC,oBAAqB,0BACrBC,WAAc,gCAGdC,SAAU,mBACVC,UAAW,oBAGXC,oBAAqB,0BACrBC,iBAAkB,6DAClBC,yBAA0B,yDAC1BC,8BAA+B,oDAC/BC,4BAA6B,+DAC7BC,wBAAyB,uDACzBC,qCAAsC,yCAGtCC,QAAS,sBACTC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,mBAAoB,+BACpBC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,oBAAqB,gCACrBC,oBAAqB,iCAEzBC,MACIjD,WACIkD,MAAO,WAEX1C,SACI0C,MAAO,YAEX9C,UACI8C,MAAO,WAEX7C,YACI6C,MAAO,aAEX5C,WACI4C,MAAO,WAEXzC,iBACIyC,MAAO,SAAU,eAErBhB,qBACIgB,MAAO,WAEXf,kBACIe,MAAO,WAEXd,0BACIc,MAAO,mBAEXb,+BACIa,MAAO,2BAEXZ,6BACIY,MAAO,mBAEXX,yBACIW,MAAO,mBAEXV,sCACIU,MAAO,mBAEXvC,WACIuC,MAAO,cAEXpC,SACIoC,MAAO,SAAU,aACjBC,QAAS,WAEbvC,QACIsC,MAAO,SAAU,WACjBC,QAAS,SACTC,KAAM,SAAUC,EAAGC,GACfC,OAAOD,QAAUA,IAGzBb,SACIS,MAAO,WAEXnC,cACImC,MAAO,WAEXlC,kBACIkC,MAAO,WAEXjC,cACIiC,MAAO,WAEXhC,aACIgC,MAAO,WAEX/B,YACI+B,MAAO,WAEX9B,SACI8B,MAAO,SAAU,cACjBC,QAAS,WAEb9B,WACI6B,MAAO,SAAU,cAErB5B,iBACI4B,MAAO,SAAU,cAErB3B,gBACI2B,MAAO,WAEXxB,uBACIwB,MAAO,cAEXvB,iBACIuB,MAAO,WAEXtB,UACIsB,MAAO,WAEXnB,YACImB,MAAO,cAQnBM,QAAQtE,QACJC,QAASH,YAIbC,WAAYL","file":"app.js","sourceRoot":"/js"}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
define(["jquery","app/init","summernote"],(e,a)=>{"use strict";return e.extend(e.summernote.plugins,{lengthField:function(a){e.summernote.ui,a.memo("button.lengthField",()=>e("<kbd>",{class:["text-right","txt-color"].join(" ")}));let t=e=>{let t=a.options.maxTextLength,n=e.length,s=a.layoutInfo.toolbar.find("kbd"),f=t-n;s.text(f).data("charCount",f),s.toggleClass("txt-color-red",t<=n),a.layoutInfo.toolbar.find(".btn-save").prop("disabled",t<n)};this.events={"summernote.init":function(e,n){t(a.$note.summernote("code"))},"summernote.change":function(e,a){t(a)}}}}),e.extend(e.summernote.plugins,{discardBtn:function(a){let t=e.summernote.ui;a.memo("button.discardBtn",()=>{let n=t.button({contents:'<i class="fas fa-fw fa-ban"/>',container:"body",click:function(){e(this).confirmation("show")}}).render(),s={container:"body",placement:"top",btnCancelClass:"btn btn-sm btn-default",btnCancelLabel:"cancel",title:"discard changes",btnOkClass:"btn btn-sm btn-warning",btnOkLabel:"discard",btnOkIcon:"fas fa-fw fa-ban",onConfirm:(e,t)=>{a.$note.summernote("reset"),a.$note.summernote("destroy")}};return n.confirmation(s),n})}}),{initSummernote:(a,t)=>{t=e.extend({},{dialogsInBody:!0,dialogsFade:!0,styleTags:["p","h2","h3","blockquote"],linkTargetBlank:!0,tableClassName:"table table-condensed table-bordered",insertTableMaxSize:{col:5,row:5},icons:{alignCenter:"fas fa-align-center",alignJustify:"fas fa-align-justify",alignLeft:"fas fa-align-left",alignRight:"fas fa-align-right",indent:"fas fa-indent",outdent:"fas fa-outdent",arrowsAlt:"fas fa-expand-arrows-alt",bold:"fas fa-bold",caret:"fas fa-caret-down",circle:"fas fa-circle",close:"fas fa-time",code:"fas fa-code",eraser:"fas fa-eraser",font:"fas fa-font",italic:"fas fa-italic",link:"fas fa-link",unlink:"fas fa-unlink",magic:"fas fa-magic",menuCheck:"fas fa-check",minus:"fas fa-minus",orderedlist:"fas fa-list-ol",pencil:"fa-pen",picture:"fas fa-image",question:"fas fa-question",redo:"fas fa-redo",square:"fas fa-square",strikethrough:"fas fa-strikethrough",subscript:"fas fa-subscript",superscript:"fas fa-superscript",table:"fas fa-table",textHeight:"fas fa-text-height",trash:"fas fa-trash",underline:"fas fa-underline",undo:"fas fa-undo",unorderedlist:"fas fa-list-ul",video:"fab fa-youtube"},colors:[["#5cb85c","#e28a0d","#d9534f","#e06fdf","#9fa8da","#e2ce48","#428bca"]],colorsName:[["Green","Orange","Red","Pink","Indigo","Yellow","Blue"]]},t),a.summernote(t)}}});
|
||||
//# sourceMappingURL=summernote.loader.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app/summernote.loader.js"],"names":["define","$","Init","extend","summernote","plugins","lengthField","context","ui","memo","class","join","updateCounter","contents","maxTextLength","options","textLength","length","counter","layoutInfo","toolbar","find","counterLeft","text","data","toggleClass","prop","this","events","summernote.init","we","e","$note","summernote.change","discardBtn","$button","button","container","click","confirmation","render","confirmationSettings","placement","btnCancelClass","btnCancelLabel","title","btnOkClass","btnOkLabel","btnOkIcon","onConfirm","target","initSummernote","element","dialogsInBody","dialogsFade","styleTags","linkTargetBlank","tableClassName","insertTableMaxSize","col","row","icons","alignCenter","alignJustify","alignLeft","alignRight","indent","outdent","arrowsAlt","bold","caret","circle","close","code","eraser","font","italic","link","unlink","magic","menuCheck","minus","orderedlist","pencil","picture","question","redo","square","strikethrough","subscript","superscript","table","textHeight","trash","underline","undo","unorderedlist","video","colors","colorsName"],"mappings":"AAAAA,QACI,SACA,WACA,cACD,CAACC,EAAGC,KACH,aAkLA,OA7KID,EAAEE,OAAOF,EAAEG,WAAWC,SAIlBC,YAAa,SAAUC,GAEVN,EAAEG,WAAWI,GAGtBD,EAAQE,KAAK,qBAAsB,IACxBR,EAAE,SACLS,OAAQ,aAAc,aAAaC,KAAK,QAQhD,IAAIC,EAAiBC,IACjB,IAAIC,EAAgBP,EAAQQ,QAAQD,cAChCE,EAAaH,EAASI,OACtBC,EAAUX,EAAQY,WAAWC,QAAQC,KAAK,OAC1CC,EAAcR,EAAgBE,EAElCE,EAAQK,KAAKD,GAAaE,KAAK,YAAaF,GAC5CJ,EAAQO,YAAY,gBAAiBX,GAAiBE,GAGxCT,EAAQY,WAAWC,QAAQC,KAAK,aACtCK,KAAK,WAAYZ,EAAgBE,IAI7CW,KAAKC,QACDC,kBAAmB,SAAUC,EAAIC,GAC7BnB,EAAcL,EAAQyB,MAAM5B,WAAW,UAE3C6B,oBAAqB,SAASH,EAAIjB,GAC9BD,EAAcC,QAQ9BZ,EAAEE,OAAOF,EAAEG,WAAWC,SAIlB6B,WAAY,SAAU3B,GAClB,IACIC,EAAKP,EAAEG,WAAWI,GAGtBD,EAAQE,KAAK,oBAAqB,KAC9B,IAQI0B,EARS3B,EAAG4B,QACZvB,SAAU,gCACVwB,UAAW,OACXC,MAAO,WAEHrC,EAAE0B,MAAMY,aAAa,WAGRC,SAGjBC,GACAJ,UAAW,OACXK,UAAW,MACXC,eAAgB,yBAChBC,eAAgB,SAChBC,MAAO,kBACPC,WAAY,yBACZC,WAAY,UACZC,UAAW,mBACXC,UAAW,CAAClB,EAAGmB,KAEX3C,EAAQyB,MAAM5B,WAAW,SACzBG,EAAQyB,MAAM5B,WAAW,aAKjC,OAFA+B,EAAQI,aAAaE,GAEdN,QAyFnBgB,eA9EiB,CAACC,EAASrC,KAsE3BA,EAAUd,EAAEE,WAnERkD,eAAe,EACfC,aAAa,EAKbC,WAAY,IAAK,KAAM,KAAM,cAC7BC,iBAAiB,EACjBC,eAAgB,uCAChBC,oBACIC,IAAK,EACLC,IAAK,GAETC,OAEIC,YAAe,sBACfC,aAAgB,uBAChBC,UAAa,oBACbC,WAAc,qBAOdC,OAAU,gBACVC,QAAW,iBACXC,UAAa,2BACbC,KAAQ,cACRC,MAAS,oBACTC,OAAU,gBACVC,MAAS,cACTC,KAAQ,cACRC,OAAU,gBACVC,KAAQ,cAERC,OAAU,gBACVC,KAAQ,cACRC,OAAU,gBACVC,MAAS,eACTC,UAAa,eACbC,MAAS,eACTC,YAAe,iBACfC,OAAU,SACVC,QAAW,eACXC,SAAY,kBACZC,KAAQ,cACRC,OAAU,gBACVC,cAAiB,uBACjBC,UAAa,mBACbC,YAAe,qBACfC,MAAS,eACTC,WAAc,qBACdC,MAAS,eACTC,UAAa,mBACbC,KAAQ,cACRC,cAAiB,iBACjBC,MAAS,kBAEbC,SACK,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,YAEvEC,aACK,QAAS,SAAU,MAAO,OAAQ,SAAU,SAAU,UAIxBpF,GAEvCqC,EAAQhD,WAAWW","file":"summernote.loader.js","sourceRoot":"/js"}
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";let window={};self.importScripts(self.name);let MsgWorker=window.MsgWorker,socket=null,ports=[],characterPorts=[],initSocket=e=>{let t=new MsgWorker("ws:open");null===socket?((socket=new WebSocket(e)).onopen=(e=>{t.meta({readyState:socket.readyState}),sendToCurrentPort(t)}),socket.onmessage=(e=>{let t=JSON.parse(e.data),r=new MsgWorker("ws:send");r.task(t.task),r.meta({readyState:this.readyState,characterIds:t.characterIds}),r.data(t.load),broadcastPorts(r)}),socket.onclose=(e=>{let t=new MsgWorker("ws:closed");t.meta({readyState:socket.readyState,code:e.code,reason:e.reason,wasClean:e.wasClean}),broadcastPorts(t),socket=null}),socket.onerror=(e=>{let t=new MsgWorker("ws:error");t.meta({readyState:socket.readyState}),sendToCurrentPort(t)})):(t.meta({readyState:socket.readyState}),sendToCurrentPort(t))},sendToCurrentPort=e=>{ports[ports.length-1].postMessage(e)},broadcastPorts=e=>{let t=ports,r=e.meta();r&&r.characterIds&&"undefined"!==r.characterIds&&r.characterIds instanceof Array&&(t=getPortsByCharacterIds(r.characterIds));for(let r=0;r<t.length;r++)t[r].postMessage(e)},addPort=(e,t)=>{(t=parseInt(t))>0?characterPorts.push({characterId:t,port:e}):ports.push(e)},getPortsByCharacterIds=e=>{let t=[];for(let r=0;r<characterPorts.length;r++)for(let a=0;a<e.length;a++)characterPorts[r].characterId===e[a]&&t.push(characterPorts[r].port);return t};self.addEventListener("connect",e=>{let t=e.ports[0];addPort(t),t.addEventListener("message",e=>{let r=e.data;switch(Object.setPrototypeOf(r,MsgWorker.prototype),r.command){case"ws:init":let e=r.data();addPort(t,e.characterId),initSocket(e.uri);break;case"ws:send":let a={task:r.task(),load:r.data()};socket.send(JSON.stringify(a))}},!1),t.start()},!1);
|
||||
//# sourceMappingURL=map.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app/worker/map.js"],"names":["window","self","importScripts","name","MsgWorker","socket","ports","characterPorts","initSocket","uri","MsgWorkerOpen","WebSocket","onopen","e","meta","readyState","sendToCurrentPort","onmessage","response","JSON","parse","data","MsgWorkerSend","task","this","characterIds","load","broadcastPorts","onclose","closeEvent","MsgWorkerClosed","code","reason","wasClean","onerror","MsgWorkerError","length","postMessage","sentToPorts","Array","getPortsByCharacterIds","i","addPort","port","characterId","parseInt","push","j","addEventListener","event","MsgWorkerMessage","Object","setPrototypeOf","prototype","command","MsgSocket","send","stringify","start"],"mappings":"AAAA,aAGA,IAAIA,UAGJC,KAAKC,cAAeD,KAAKE,MAEzB,IAAIC,UAAYJ,OAAOI,UACnBC,OAAS,KACTC,SACAC,kBAGAC,WAAcC,IACd,IAAIC,EAAgB,IAAIN,UAAU,WAEpB,OAAXC,SACCA,OAAS,IAAIM,UAAUF,IAGhBG,OAAS,CAACC,IACbH,EAAcI,MACVC,WAAYV,OAAOU,aAGvBC,kBAAkBN,KAItBL,OAAOY,UAAY,CAACJ,IAChB,IAAIK,EAAWC,KAAKC,MAAMP,EAAEQ,MAExBC,EAAgB,IAAIlB,UAAU,WAClCkB,EAAcC,KAAML,EAASK,MAC7BD,EAAcR,MACVC,WAAYS,KAAKT,WACjBU,aAAcP,EAASO,eAE3BH,EAAcD,KAAMH,EAASQ,MAE7BC,eAAeL,KAInBjB,OAAOuB,QAAU,CAACC,IACd,IAAIC,EAAkB,IAAI1B,UAAU,aACpC0B,EAAgBhB,MACZC,WAAYV,OAAOU,WACnBgB,KAAMF,EAAWE,KACjBC,OAAQH,EAAWG,OACnBC,SAAUJ,EAAWI,WAGzBN,eAAeG,GACfzB,OAAS,OAIbA,OAAO6B,QAAU,CAACrB,IACd,IAAIsB,EAAiB,IAAI/B,UAAU,YACnC+B,EAAerB,MACXC,WAAYV,OAAOU,aAGvBC,kBAAkBmB,OAItBzB,EAAcI,MACVC,WAAYV,OAAOU,aAEvBC,kBAAkBN,KAKtBM,kBAAqBU,IACrBpB,MAAMA,MAAM8B,OAAS,GAAGC,YAAYX,IAGpCC,eAAkBD,IAElB,IAAIY,EAAchC,MAGdQ,EAAOY,EAAKZ,OAEZA,GACAA,EAAKW,cACiB,cAAtBX,EAAKW,cACLX,EAAKW,wBAAwBc,QAG7BD,EAAcE,uBAAuB1B,EAAKW,eAG9C,IAAI,IAAIgB,EAAI,EAAGA,EAAIH,EAAYF,OAAQK,IACnCH,EAAYG,GAAGJ,YAAYX,IAK/BgB,QAAU,CAACC,EAAMC,MACjBA,EAAcC,SAASD,IAEN,EACbrC,eAAeuC,MACXF,YAAaA,EACbD,KAAMA,IAGVrC,MAAMwC,KAAKH,IAIfH,uBAA0Bf,IAC1B,IAAInB,KAEJ,IAAI,IAAImC,EAAI,EAAGA,EAAIlC,eAAe6B,OAAQK,IACtC,IAAI,IAAIM,EAAI,EAAGA,EAAItB,EAAaW,OAAQW,IACjCxC,eAAekC,GAAGG,cAAgBnB,EAAasB,IAC9CzC,EAAMwC,KAAKvC,eAAekC,GAAGE,MAKzC,OAAOrC,GAIXL,KAAK+C,iBAAiB,UAAYC,IAC9B,IAAIN,EAAOM,EAAM3C,MAAM,GACvBoC,QAAQC,GAERA,EAAKK,iBAAiB,UAAYnC,IAC9B,IAAIqC,EAAmBrC,EAAEQ,KAGzB,OAFA8B,OAAOC,eAAeF,EAAkB9C,UAAUiD,WAE3CH,EAAiBI,SACpB,IAAK,UACD,IAAIjC,EAAO6B,EAAiB7B,OAE5BqB,QAAQC,EAAMtB,EAAKuB,aACnBpC,WAAWa,EAAKZ,KAChB,MACJ,IAAK,UACD,IAAI8C,GACAhC,KAAM2B,EAAiB3B,OACvBG,KAAMwB,EAAiB7B,QAG3BhB,OAAOmD,KAAKrC,KAAKsC,UAAUF,OAMpC,GAEHZ,EAAKe,UACN","file":"map.js","sourceRoot":"/js"}
|
||||
@@ -1,2 +0,0 @@
|
||||
window.MsgWorker=class{constructor(s){this.cmd=s,this.msgTask="",this.msgMeta=null,this.msgBody=null}get command(){return this.cmd}task(s){return s&&(this.msgTask=s),this.msgTask}meta(s){return s&&(this.msgMeta=s),this.msgMeta}data(s){return s&&(this.msgBody=s),this.msgBody}};
|
||||
//# sourceMappingURL=message.js.map
|
||||
@@ -1 +0,0 @@
|
||||
9<01>Ĵ9<C4B4>F<EFBFBD>0~y<><18>|uK<75>v0<76>Iw<49><77>.<2E>x<14><><EFBFBD><EFBFBD>(O<><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><12><>zʘL0<4C><05><><EFBFBD><EFBFBD>ů<EFBFBD>r<16>_D<5F>? <1<><31>P(<28>LFj<46><1C><><EFBFBD>H<EFBFBD><48><EFBFBD><EFBFBD><EFBFBD>26hL<68>3<EFBFBD><33>-<0C>0+<2B> ;<3B><0F>#<23>dMFj=<3D><><EFBFBD><EFBFBD><EFBFBD>`+s$<24>P=.a<>veS<65>r<EFBFBD>z<EFBFBD><7A><EFBFBD>>
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app/worker/message.js"],"names":["window","MsgWorker","[object Object]","cmd","this","msgTask","msgMeta","msgBody","command","task","metaData","data"],"mappings":"AAAAA,OAAOC,gBAEHC,YAAYC,GAIRC,KAAKD,IAAMA,EAMXC,KAAKC,QAAU,GAMfD,KAAKE,QAAU,KAMfF,KAAKG,QAAU,KAGnBC,cACI,OAAOJ,KAAKD,IAGhBD,KAAKO,GAKD,OAJGA,IACCL,KAAKC,QAAUI,GAGZL,KAAKC,QAGhBH,KAAKQ,GAKD,OAJGA,IACCN,KAAKE,QAAUI,GAGZN,KAAKE,QAGhBJ,KAAKS,GAKD,OAJGA,IACCP,KAAKG,QAAUI,GAGZP,KAAKG","file":"message.js","sourceRoot":"/js"}
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery","blueImpGallery"],t):t(window.jQuery,window.blueimp.Gallery)}(function(t,o){"use strict";t.extend(o.prototype.options,{useBootstrapModal:!0});var e=o.prototype.close,n=o.prototype.imageFactory,i=o.prototype.videoFactory,r=o.prototype.textFactory;t.extend(o.prototype,{modalFactory:function(o,e,n,i){if(!this.options.useBootstrapModal||n)return i.call(this,o,e,n);var r=this,a=t(this.container).children(".modal").clone().css("display","block").on("click",function(t){t.target!==a[0]&&t.target!==a.children()[0]||(t.preventDefault(),t.stopPropagation(),r.close())}),c=i.call(this,o,function(t){e({type:t.type,target:a[0]}),a.addClass("in")},n);return a.find(".modal-title").text(c.title||String.fromCharCode(160)),a.find(".modal-body").append(c),a[0]},imageFactory:function(t,o,e){return this.modalFactory(t,o,e,n)},videoFactory:function(t,o,e){return this.modalFactory(t,o,e,i)},textFactory:function(t,o,e){return this.modalFactory(t,o,e,r)},close:function(){this.container.find(".modal").removeClass("in"),e.call(this)}})});
|
||||
//# sourceMappingURL=bootstrap-image-gallery.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["lib/bootstrap-image-gallery.js"],"names":["factory","define","amd","window","jQuery","blueimp","Gallery","$","extend","prototype","options","useBootstrapModal","close","imageFactory","videoFactory","textFactory","modalFactory","obj","callback","factoryInterface","this","call","that","modal","container","children","clone","css","on","event","target","preventDefault","stopPropagation","element","type","addClass","find","text","title","String","fromCharCode","append","removeClass"],"mappings":"CAaE,SAAUA,GACR,aACsB,mBAAXC,QAAyBA,OAAOC,IACvCD,QACI,SACA,kBACDD,GAEHA,EACIG,OAAOC,OACPD,OAAOE,QAAQC,SAV1B,CAaC,SAAUC,EAAGD,GACX,aAEAC,EAAEC,OAAOF,EAAQG,UAAUC,SACvBC,mBAAmB,IAGvB,IAAIC,EAAQN,EAAQG,UAAUG,MAC1BC,EAAeP,EAAQG,UAAUI,aACjCC,EAAeR,EAAQG,UAAUK,aACjCC,EAAcT,EAAQG,UAAUM,YAEpCR,EAAEC,OAAOF,EAAQG,WACbO,aAAc,SAAUC,EAAKC,EAAUC,EAAkBnB,GACrD,IAAKoB,KAAKV,QAAQC,mBAAqBQ,EACnC,OAAOnB,EAAQqB,KAAKD,KAAMH,EAAKC,EAAUC,GAE7C,IAAIG,EAAOF,KAEPG,EADgBhB,EAAEa,KAAKI,WAAWC,SAAS,UACrBC,QAAQC,IAAI,UAAW,SAASC,GAAG,QAAS,SAAUC,GAGxEA,EAAMC,SAAWP,EAAM,IACvBM,EAAMC,SAAWP,EAAME,WAAW,KAClCI,EAAME,iBACNF,EAAMG,kBACNV,EAAKV,WAGTqB,EAAUjC,EAAQqB,KAAKD,KAAMH,EAAK,SAAUY,GAC5CX,GACIgB,KAAML,EAAMK,KACZJ,OAAQP,EAAM,KAElBA,EAAMY,SAAS,OAChBhB,GAIH,OAHAI,EAAMa,KAAK,gBAAgBC,KAAKJ,EAAQK,OAASC,OAAOC,aAAa,MACrEjB,EAAMa,KAAK,eAAeK,OAAOR,GAE1BV,EAAM,IAGjBV,aAAc,SAAUI,EAAKC,EAAUC,GACnC,OAAOC,KAAKJ,aAAaC,EAAKC,EAAUC,EAAkBN,IAG9DC,aAAc,SAAUG,EAAKC,EAAUC,GACnC,OAAOC,KAAKJ,aAAaC,EAAKC,EAAUC,EAAkBL,IAG9DC,YAAa,SAAUE,EAAKC,EAAUC,GAClC,OAAOC,KAAKJ,aAAaC,EAAKC,EAAUC,EAAkBJ,IAG9DH,MAAO,WACHQ,KAAKI,UAAUY,KAAK,UAAUM,YAAY,MAC1C9B,EAAMS,KAAKD","file":"bootstrap-image-gallery.js","sourceRoot":"/js"}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):jQuery&&!jQuery.fn.hoverIntent&&e(jQuery)}(function(e){"use strict";var t,n,i={interval:100,sensitivity:6,timeout:0},o=0,u=function(e){t=e.pageX,n=e.pageY},r=function(e,i,o,v){if(Math.sqrt((o.pX-t)*(o.pX-t)+(o.pY-n)*(o.pY-n))<v.sensitivity)return i.off(o.event,u),delete o.timeoutId,o.isActive=!0,e.pageX=t,e.pageY=n,delete o.pX,delete o.pY,v.over.apply(i[0],[e]);o.pX=t,o.pY=n,o.timeoutId=setTimeout(function(){r(e,i,o,v)},v.interval)};e.fn.hoverIntent=function(t,n,v){var a=o++,s=e.extend({},i);e.isPlainObject(t)?(s=e.extend(s,t),e.isFunction(s.out)||(s.out=s.over)):s=e.isFunction(n)?e.extend(s,{over:t,out:n,selector:v}):e.extend(s,{over:t,out:t,selector:n});var f=function(t){var n=e.extend({},t),i=e(this),o=i.data("hoverIntent");o||i.data("hoverIntent",o={});var v=o[a];v||(o[a]=v={id:a}),v.timeoutId&&(v.timeoutId=clearTimeout(v.timeoutId));var f=v.event="mousemove.hoverIntent.hoverIntent"+a;if("mouseenter"===t.type){if(v.isActive)return;v.pX=n.pageX,v.pY=n.pageY,i.off(f,u).on(f,u),v.timeoutId=setTimeout(function(){r(n,i,v,s)},s.interval)}else{if(!v.isActive)return;i.off(f,u),v.timeoutId=setTimeout(function(){!function(e,t,n,i){delete t.data("hoverIntent")[n.id],i.apply(t[0],[e])}(n,i,v,s.out)},s.timeout)}};return this.on({"mouseenter.hoverIntent":f,"mouseleave.hoverIntent":f},s.selector)}});
|
||||
//# sourceMappingURL=jquery.hoverIntent.minified.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["lib/jquery.hoverIntent.minified.js"],"names":["factory","define","amd","jQuery","fn","hoverIntent","$","cX","cY","_cfg","interval","sensitivity","timeout","INSTANCE_COUNT","track","ev","pageX","pageY","compare","$el","s","cfg","Math","sqrt","pX","pY","off","event","timeoutId","isActive","over","apply","setTimeout","handlerIn","handlerOut","selector","instanceId","extend","isPlainObject","isFunction","out","handleHover","e","this","hoverIntentData","data","state","id","clearTimeout","mousemove","type","on","delay","mouseenter.hoverIntent","mouseleave.hoverIntent"],"mappings":"CAQC,SAASA,GAAS,aAAa,mBAAmBC,QAAQA,OAAOC,IAAID,QAAQ,UAAUD,GAASG,SAASA,OAAOC,GAAGC,aAAaL,EAAQG,QAAxI,CAAiJ,SAASG,GAAG,aAAa,IAAIC,EAAGC,EAAGC,GAAMC,SAAS,IAAIC,YAAY,EAAEC,QAAQ,GAAGC,EAAe,EAAEC,EAAM,SAASC,GAAIR,EAAGQ,EAAGC,MAAMR,EAAGO,EAAGE,OAAOC,EAAQ,SAASH,EAAGI,EAAIC,EAAEC,GAAK,GAAGC,KAAKC,MAAMH,EAAEI,GAAGjB,IAAKa,EAAEI,GAAGjB,IAAKa,EAAEK,GAAGjB,IAAKY,EAAEK,GAAGjB,IAAKa,EAAIV,YAAY,OAAOQ,EAAIO,IAAIN,EAAEO,MAAMb,UAAcM,EAAEQ,UAAUR,EAAES,UAAS,EAAGd,EAAGC,MAAMT,EAAGQ,EAAGE,MAAMT,SAAUY,EAAEI,UAAUJ,EAAEK,GAAGJ,EAAIS,KAAKC,MAAMZ,EAAI,IAAIJ,IAAKK,EAAEI,GAAGjB,EAAGa,EAAEK,GAAGjB,EAAGY,EAAEQ,UAAUI,WAAW,WAAWd,EAAQH,EAAGI,EAAIC,EAAEC,IAAMA,EAAIX,WAA4GJ,EAAEF,GAAGC,YAAY,SAAS4B,EAAUC,EAAWC,GAAU,IAAIC,EAAWvB,IAAiBQ,EAAIf,EAAE+B,UAAU5B,GAAMH,EAAEgC,cAAcL,IAAYZ,EAAIf,EAAE+B,OAAOhB,EAAIY,GAAW3B,EAAEiC,WAAWlB,EAAImB,OAAOnB,EAAImB,IAAInB,EAAIS,OAAOT,EAAIf,EAAEiC,WAAWL,GAAY5B,EAAE+B,OAAOhB,GAAKS,KAAKG,EAAUO,IAAIN,EAAWC,SAASA,IAAW7B,EAAE+B,OAAOhB,GAAKS,KAAKG,EAAUO,IAAIP,EAAUE,SAASD,IAAa,IAAIO,EAAY,SAASC,GAAG,IAAI3B,EAAGT,EAAE+B,UAAUK,GAAGvB,EAAIb,EAAEqC,MAAMC,EAAgBzB,EAAI0B,KAAK,eAAeD,GAAiBzB,EAAI0B,KAAK,cAAcD,MAAoB,IAAIE,EAAMF,EAAgBR,GAAYU,IAAQF,EAAgBR,GAAYU,GAAOC,GAAGX,IAAaU,EAAMlB,YAAYkB,EAAMlB,UAAUoB,aAAaF,EAAMlB,YAAY,IAAIqB,EAAUH,EAAMnB,MAAM,oCAAoCS,EAAW,GAAG,eAAeM,EAAEQ,KAAK,CAAC,GAAGJ,EAAMjB,SAAS,OAAOiB,EAAMtB,GAAGT,EAAGC,MAAM8B,EAAMrB,GAAGV,EAAGE,MAAME,EAAIO,IAAIuB,EAAUnC,GAAOqC,GAAGF,EAAUnC,GAAOgC,EAAMlB,UAAUI,WAAW,WAAWd,EAAQH,EAAGI,EAAI2B,EAAMzB,IAAMA,EAAIX,cAAc,CAAC,IAAIoC,EAAMjB,SAAS,OAAOV,EAAIO,IAAIuB,EAAUnC,GAAOgC,EAAMlB,UAAUI,WAAW,YAA9nC,SAASjB,EAAGI,EAAIC,EAAEoB,UAAmBrB,EAAI0B,KAAK,eAAezB,EAAE2B,IAAIP,EAAIT,MAAMZ,EAAI,IAAIJ,IAAojCqC,CAAMrC,EAAGI,EAAI2B,EAAMzB,EAAImB,MAAMnB,EAAIT,WAAW,OAAO+B,KAAKQ,IAAIE,yBAAyBZ,EAAYa,yBAAyBb,GAAapB,EAAIc","file":"jquery.hoverIntent.minified.js","sourceRoot":"/js"}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
!function(o,s){"function"==typeof define&&define.amd?define("pnotify.buttons",["jquery","pnotify"],s):"object"==typeof exports&&"undefined"!=typeof module?module.exports=s(require("jquery"),require("./pnotify")):s(o.jQuery,o.PNotify)}("undefined"!=typeof window?window:this,function(o,s){return s.prototype.options.buttons={closer:!0,closer_hover:!0,sticker:!0,sticker_hover:!0,show_on_nonblock:!1,labels:{close:"Close",stick:"Stick",unstick:"Unstick"},classes:{closer:null,pin_up:null,pin_down:null}},s.prototype.modules.buttons={init:function(s,i){var n=this;s.elem.on({mouseenter:function(o){!n.options.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.sticker.trigger("pnotify:buttons:toggleStick").css("visibility","visible"),!n.options.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.closer.css("visibility","visible")},mouseleave:function(o){n.options.sticker_hover&&n.sticker.css("visibility","hidden"),n.options.closer_hover&&n.closer.css("visibility","hidden")}}),this.sticker=o("<div />",{class:"ui-pnotify-sticker","aria-role":"button","aria-pressed":s.options.hide?"false":"true",tabindex:"0",title:s.options.hide?i.labels.stick:i.labels.unstick,css:{cursor:"pointer",visibility:i.sticker_hover?"hidden":"visible"},click:function(){s.options.hide=!s.options.hide,s.options.hide?s.queueRemove():s.cancelRemove(),o(this).trigger("pnotify:buttons:toggleStick")}}).bind("pnotify:buttons:toggleStick",function(){var i=null===n.options.classes.pin_up?s.styles.pin_up:n.options.classes.pin_up,e=null===n.options.classes.pin_down?s.styles.pin_down:n.options.classes.pin_down;o(this).attr("title",s.options.hide?n.options.labels.stick:n.options.labels.unstick).children().attr("class","").addClass(s.options.hide?i:e).attr("aria-pressed",s.options.hide?"false":"true")}).append("<span />").trigger("pnotify:buttons:toggleStick").prependTo(s.container),(!i.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.sticker.css("display","none"),this.closer=o("<div />",{class:"ui-pnotify-closer","aria-role":"button",tabindex:"0",title:i.labels.close,css:{cursor:"pointer",visibility:i.closer_hover?"hidden":"visible"},click:function(){s.remove(!1),n.sticker.css("visibility","hidden"),n.closer.css("visibility","hidden")}}).append(o("<span />",{class:null===i.classes.closer?s.styles.closer:i.classes.closer})).prependTo(s.container),(!i.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.closer.css("display","none")},update:function(o,s){!s.closer||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.closer.css("display","none"):s.closer&&this.closer.css("display","block"),!s.sticker||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.sticker.css("display","none"):s.sticker&&this.sticker.css("display","block"),this.sticker.trigger("pnotify:buttons:toggleStick"),this.closer.find("span").attr("class","").addClass(null===s.classes.closer?o.styles.closer:s.classes.closer),s.sticker_hover?this.sticker.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.sticker.css("visibility","visible"),s.closer_hover?this.closer.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.closer.css("visibility","visible")}},o.extend(s.styling.brighttheme,{closer:"brighttheme-icon-closer",pin_up:"brighttheme-icon-sticker",pin_down:"brighttheme-icon-sticker brighttheme-icon-stuck"}),o.extend(s.styling.bootstrap3,{closer:"glyphicon glyphicon-remove",pin_up:"glyphicon glyphicon-pause",pin_down:"glyphicon glyphicon-play"}),o.extend(s.styling.fontawesome,{closer:"fa fa-times",pin_up:"fa fa-pause",pin_down:"fa fa-play"}),s});
|
||||
//# sourceMappingURL=pnotify.buttons.js.map
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["lib/pnotify/pnotify.buttons.js"],"names":["root","factory","define","amd","exports","module","require","jQuery","PNotify","window","this","$","prototype","options","buttons","closer","closer_hover","sticker","sticker_hover","show_on_nonblock","labels","close","stick","unstick","classes","pin_up","pin_down","modules","init","notice","that","elem","on","mouseenter","e","nonblock","trigger","css","mouseleave","class","aria-role","aria-pressed","hide","tabindex","title","cursor","visibility","click","queueRemove","cancelRemove","bind","styles","attr","children","addClass","append","prependTo","container","remove","update","find","extend","styling","brighttheme","bootstrap3","fontawesome"],"mappings":"CACC,SAAUA,EAAMC,GACO,mBAAXC,QAAyBA,OAAOC,IAEzCD,OAAO,mBAAoB,SAAU,WAAYD,GACrB,iBAAZG,SAA0C,oBAAXC,OAE/CA,OAAOD,QAAUH,EAAQK,QAAQ,UAAWA,QAAQ,cAGpDL,EAAQD,EAAKO,OAAQP,EAAKQ,SAT9B,CAWoB,oBAAXC,OAAyBA,OAASC,KAAM,SAASC,EAAGH,GAsJ3D,OArJAA,EAAQI,UAAUC,QAAQC,SAExBC,QAAQ,EAERC,cAAc,EAEdC,SAAS,EAETC,eAAe,EAEfC,kBAAkB,EAElBC,QACEC,MAAO,QACPC,MAAO,QACPC,QAAS,WAGXC,SACET,OAAQ,KACRU,OAAQ,KACRC,SAAU,OAGdlB,EAAQI,UAAUe,QAAQb,SACxBc,KAAM,SAASC,EAAQhB,GACrB,IAAIiB,EAAOpB,KACXmB,EAAOE,KAAKC,IACVC,WAAc,SAASC,IAEjBJ,EAAKjB,QAAQI,SAAcY,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAaL,EAAKjB,QAAQM,kBAC1GW,EAAKb,QAAQmB,QAAQ,+BAA+BC,IAAI,aAAc,YAEpEP,EAAKjB,QAAQE,QAAac,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAaL,EAAKjB,QAAQM,kBACzGW,EAAKf,OAAOsB,IAAI,aAAc,YAGlCC,WAAc,SAASJ,GAEjBJ,EAAKjB,QAAQK,eACfY,EAAKb,QAAQoB,IAAI,aAAc,UAE7BP,EAAKjB,QAAQG,cACfc,EAAKf,OAAOsB,IAAI,aAAc,aAMpC3B,KAAKO,QAAUN,EAAE,WACf4B,MAAS,qBACTC,YAAa,SACbC,eAAgBZ,EAAOhB,QAAQ6B,KAAO,QAAU,OAChDC,SAAY,IACZC,MAASf,EAAOhB,QAAQ6B,KAAO7B,EAAQO,OAAOE,MAAQT,EAAQO,OAAOG,QACrEc,KACEQ,OAAU,UACVC,WAAcjC,EAAQK,cAAgB,SAAW,WAEnD6B,MAAS,WACPlB,EAAOhB,QAAQ6B,MAAQb,EAAOhB,QAAQ6B,KAClCb,EAAOhB,QAAQ6B,KACjBb,EAAOmB,cAEPnB,EAAOoB,eAETtC,EAAED,MAAM0B,QAAQ,kCAGnBc,KAAK,8BAA+B,WACnC,IAAIzB,EAAyC,OAAhCK,EAAKjB,QAAQW,QAAQC,OAAkBI,EAAOsB,OAAO1B,OAASK,EAAKjB,QAAQW,QAAQC,OAC5FC,EAA6C,OAAlCI,EAAKjB,QAAQW,QAAQE,SAAoBG,EAAOsB,OAAOzB,SAAWI,EAAKjB,QAAQW,QAAQE,SACtGf,EAAED,MACD0C,KAAK,QAASvB,EAAOhB,QAAQ6B,KAAOZ,EAAKjB,QAAQO,OAAOE,MAAQQ,EAAKjB,QAAQO,OAAOG,SACpF8B,WACAD,KAAK,QAAS,IACdE,SAASzB,EAAOhB,QAAQ6B,KAAOjB,EAASC,GACxC0B,KAAK,eAAgBvB,EAAOhB,QAAQ6B,KAAO,QAAU,UAEvDa,OAAO,YACPnB,QAAQ,+BACRoB,UAAU3B,EAAO4B,aACb5C,EAAQI,SAAYY,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,mBAC/FT,KAAKO,QAAQoB,IAAI,UAAW,QAI9B3B,KAAKK,OAASJ,EAAE,WACd4B,MAAS,oBACTC,YAAa,SACbG,SAAY,IACZC,MAAS/B,EAAQO,OAAOC,MACxBgB,KAAQQ,OAAU,UAAWC,WAAcjC,EAAQG,aAAe,SAAW,WAC7E+B,MAAS,WACPlB,EAAO6B,QAAO,GACd5B,EAAKb,QAAQoB,IAAI,aAAc,UAC/BP,EAAKf,OAAOsB,IAAI,aAAc,aAGjCkB,OAAO5C,EAAE,YAAa4B,MAAoC,OAA3B1B,EAAQW,QAAQT,OAAkBc,EAAOsB,OAAOpC,OAASF,EAAQW,QAAQT,UACxGyC,UAAU3B,EAAO4B,aACb5C,EAAQE,QAAWc,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,mBAC9FT,KAAKK,OAAOsB,IAAI,UAAW,SAG/BsB,OAAQ,SAAS9B,EAAQhB,IAElBA,EAAQE,QAAWc,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,iBAC9FT,KAAKK,OAAOsB,IAAI,UAAW,QAClBxB,EAAQE,QACjBL,KAAKK,OAAOsB,IAAI,UAAW,UAExBxB,EAAQI,SAAYY,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,iBAC/FT,KAAKO,QAAQoB,IAAI,UAAW,QACnBxB,EAAQI,SACjBP,KAAKO,QAAQoB,IAAI,UAAW,SAG9B3B,KAAKO,QAAQmB,QAAQ,+BAErB1B,KAAKK,OAAO6C,KAAK,QAAQR,KAAK,QAAS,IAAIE,SAAoC,OAA3BzC,EAAQW,QAAQT,OAAkBc,EAAOsB,OAAOpC,OAASF,EAAQW,QAAQT,QAEzHF,EAAQK,cACVR,KAAKO,QAAQoB,IAAI,aAAc,UACpBR,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,kBACnFT,KAAKO,QAAQoB,IAAI,aAAc,WAE7BxB,EAAQG,aACVN,KAAKK,OAAOsB,IAAI,aAAc,UACnBR,EAAOhB,QAAQsB,UAAYN,EAAOhB,QAAQsB,SAASA,WAAatB,EAAQM,kBACnFT,KAAKK,OAAOsB,IAAI,aAAc,aAIpC1B,EAAEkD,OAAOrD,EAAQsD,QAAQC,aACvBhD,OAAQ,0BACRU,OAAQ,2BACRC,SAAU,oDAEZf,EAAEkD,OAAOrD,EAAQsD,QAAQE,YACvBjD,OAAQ,6BACRU,OAAQ,4BACRC,SAAU,6BAEZf,EAAEkD,OAAOrD,EAAQsD,QAAQG,aACvBlD,OAAQ,cACRU,OAAQ,cACRC,SAAU,eAELlB","file":"pnotify.buttons.js","sourceRoot":"/js"}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
194
public/js/v1.5.2/app.js
Normal file
194
public/js/v1.5.2/app.js
Normal file
@@ -0,0 +1,194 @@
|
||||
'use strict';
|
||||
|
||||
// main script path
|
||||
var mainScriptPath = document.body.getAttribute('data-script');
|
||||
|
||||
// js baseURL. Depends on the environment.
|
||||
// e.g. use raw files (develop) or build files (production)
|
||||
var jsBaseUrl = document.body.getAttribute('data-js-path');
|
||||
|
||||
// requireJs configuration
|
||||
requirejs.config({
|
||||
baseUrl: 'js', // path for baseUrl - dynamically set !below! ("build_js" | "js")
|
||||
|
||||
paths: {
|
||||
layout: 'layout',
|
||||
conf: 'app/conf', // path for "config" files dir
|
||||
dialog: 'app/ui/dialog', // path for "dialog" files dir
|
||||
templates: '../../templates', // template dir
|
||||
img: '../../img', // images dir
|
||||
|
||||
// main views
|
||||
login: './app/login', // initial start "login page" view
|
||||
mappage: './app/mappage', // initial start "map page" view
|
||||
setup: './app/setup', // initial start "setup page" view
|
||||
admin: './app/admin', // initial start "admin page" view
|
||||
notification: './app/notification', // "notification" view
|
||||
|
||||
jquery: 'lib/jquery-3.3.1.min', // v3.3.1 jQuery
|
||||
bootstrap: 'lib/bootstrap.min', // v3.3.0 Bootstrap js code - http://getbootstrap.com/javascript
|
||||
text: 'lib/requirejs/text', // v2.0.12 A RequireJS/AMD loader plugin for loading text resources.
|
||||
mustache: 'lib/mustache.min', // v3.0.1 Javascript template engine - http://mustache.github.io
|
||||
localForage: 'lib/localforage.min', // v1.7.3 localStorage library - https://localforage.github.io/localForage/
|
||||
velocity: 'lib/velocity.min', // v1.5.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 https://www.adchsm.com/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
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
|
||||
mousewheel: 'lib/jquery.mousewheel.min', // v3.1.13 Mousewheel - https://github.com/jquery/jquery-mousewheel
|
||||
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
|
||||
morris: 'lib/morris.min', // v0.5.1 Morris.js - graphs and charts
|
||||
raphael: 'lib/raphael-min', // v2.1.2 Raphaël - required for morris (dependency)
|
||||
bootbox: 'lib/bootbox.min', // v4.4.0 Bootbox.js - custom dialogs - http://bootboxjs.com
|
||||
easyPieChart: 'lib/jquery.easypiechart.min', // v2.1.6 Easy Pie Chart - HTML 5 pie charts - http://rendro.github.io/easy-pie-chart
|
||||
peityInlineChart: 'lib/jquery.peity.min', // v3.2.1 Inline Chart - http://benpickles.github.io/peity/
|
||||
dragToSelect: 'lib/jquery.dragToSelect', // v1.1 Drag to Select - http://andreaslagerkvist.com/jquery/drag-to-select
|
||||
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.9.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.6.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
|
||||
blueImpGallery: 'lib/blueimp-gallery', // v2.21.3 Image Gallery - https://github.com/blueimp/Gallery
|
||||
blueImpGalleryHelper: 'lib/blueimp-helper', // helper function for Blue Imp Gallery
|
||||
blueImpGalleryBootstrap: 'lib/bootstrap-image-gallery', // v3.4.2 Bootstrap extension for Blue Imp Gallery - https://blueimp.github.io/Bootstrap-Image-Gallery
|
||||
bootstrapConfirmation: 'lib/bootstrap-confirmation', // v1.0.5 Bootstrap extension for inline confirm dialog - https://github.com/tavicu/bs-confirmation
|
||||
bootstrapToggle: 'lib/bootstrap-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.7 LazyLoader images - https://appelsiini.net/projects/lazyload/
|
||||
sortable: 'lib/sortable.min', // v1.6.0 Sortable - drag&drop reorder - https://github.com/rubaxa/Sortable
|
||||
|
||||
'summernote.loader': './app/summernote.loader', // v0.8.10 Summernote WYSIWYG editor -https://summernote.org
|
||||
'summernote': 'lib/summernote/summernote.min',
|
||||
|
||||
// header animation
|
||||
easePack: 'lib/EasePack.min',
|
||||
tweenLite: 'lib/TweenLite.min',
|
||||
|
||||
// datatables // v1.10.12 DataTables - https://datatables.net
|
||||
'datatables.loader': './app/datatables.loader',
|
||||
'datatables.net': 'lib/datatables/DataTables-1.10.12/js/jquery.dataTables.min',
|
||||
'datatables.net-buttons': 'lib/datatables/Buttons-1.2.1/js/dataTables.buttons.min',
|
||||
'datatables.net-buttons-html': 'lib/datatables/Buttons-1.2.1/js/buttons.html5.min',
|
||||
'datatables.net-responsive': 'lib/datatables/Responsive-2.1.0/js/dataTables.responsive.min',
|
||||
'datatables.net-select': 'lib/datatables/Select-1.2.0/js/dataTables.select.min',
|
||||
'datatables.plugins.render.ellipsis': 'lib/datatables/plugins/render/ellipsis',
|
||||
|
||||
// notification plugin
|
||||
pnotify: 'lib/pnotify/pnotify', // v3.2.1 PNotify - notification core file - https://sciactive.com/pnotify/
|
||||
'pnotify.buttons': 'lib/pnotify/pnotify.buttons', // PNotify - buttons notification extension
|
||||
'pnotify.confirm': 'lib/pnotify/pnotify.confirm', // PNotify - confirmation notification extension
|
||||
'pnotify.nonblock': 'lib/pnotify/pnotify.nonblock', // PNotify - notification non-block extension (hover effect)
|
||||
'pnotify.desktop': 'lib/pnotify/pnotify.desktop', // PNotify - desktop push notification extension
|
||||
'pnotify.history': 'lib/pnotify/pnotify.history', // PNotify - history push notification history extension
|
||||
'pnotify.callbacks': 'lib/pnotify/pnotify.callbacks', // PNotify - callbacks push notification extension
|
||||
'pnotify.reference': 'lib/pnotify/pnotify.reference' // PNotify - reference push notification extension
|
||||
},
|
||||
shim: {
|
||||
bootstrap: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
farahey: {
|
||||
deps: ['jsPlumb']
|
||||
},
|
||||
velocity: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
velocityUI: {
|
||||
deps: ['velocity']
|
||||
},
|
||||
slidebars: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
customScrollbar: {
|
||||
deps: ['jquery', 'mousewheel']
|
||||
},
|
||||
'datatables.loader': {
|
||||
deps: ['jquery']
|
||||
},
|
||||
'datatables.net': {
|
||||
deps: ['jquery']
|
||||
},
|
||||
'datatables.net-buttons': {
|
||||
deps: ['datatables.net']
|
||||
},
|
||||
'datatables.net-buttons-html': {
|
||||
deps: ['datatables.net-buttons']
|
||||
},
|
||||
'datatables.net-responsive': {
|
||||
deps: ['datatables.net']
|
||||
},
|
||||
'datatables.net-select': {
|
||||
deps: ['datatables.net']
|
||||
},
|
||||
'datatables.plugins.render.ellipsis': {
|
||||
deps: ['datatables.net']
|
||||
},
|
||||
xEditable: {
|
||||
deps: ['bootstrap']
|
||||
},
|
||||
bootbox: {
|
||||
deps: ['jquery', 'bootstrap'],
|
||||
exports: 'bootbox'
|
||||
},
|
||||
morris: {
|
||||
deps: ['jquery', 'raphael'],
|
||||
exports: 'Morris',
|
||||
init: function ($, Raphael) {
|
||||
window.Raphael = Raphael;
|
||||
}
|
||||
},
|
||||
pnotify: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
easyPieChart: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
peityInlineChart: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
dragToSelect: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
hoverIntent: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
fullScreen: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
select2: {
|
||||
deps: ['jquery', 'mousewheel'],
|
||||
exports: 'Select2'
|
||||
},
|
||||
validator: {
|
||||
deps: ['jquery', 'bootstrap']
|
||||
},
|
||||
lazylinepainter: {
|
||||
deps: ['jquery', 'bootstrap']
|
||||
},
|
||||
blueImpGallery: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
bootstrapConfirmation: {
|
||||
deps: ['bootstrap']
|
||||
},
|
||||
bootstrapToggle: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
lazyload: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
summernote: {
|
||||
deps: ['jquery']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// switch baseUrl to js "build_js" in production environment
|
||||
// this has no effect for js build process!
|
||||
// check build.js for build configuration
|
||||
require.config({
|
||||
baseUrl: jsBaseUrl
|
||||
});
|
||||
|
||||
// load the main app module -> initial app start
|
||||
requirejs( [mainScriptPath] );
|
||||
93
public/js/v1.5.2/app/admin.js
Normal file
93
public/js/v1.5.2/app/admin.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Main "admin" page
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'datatables.loader'
|
||||
], ($, Init, Util) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
triggerOverlayClass: 'pf-overlay-trigger' // class for
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
let setPageObserver = () => {
|
||||
$('.' + config.triggerOverlayClass).on('click', function(e){
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay();
|
||||
});
|
||||
|
||||
$('body').initTooltips();
|
||||
|
||||
// set fieldset toggled by checkbox ---------------------------------------------------------------------------
|
||||
$('input[type="checkbox"][data-target]').on('change', function(){
|
||||
let targetId = $(this).attr('data-target');
|
||||
if(targetId){
|
||||
let targetElement = $('[data-id="' + targetId + '"]');
|
||||
let targetFormFields = targetElement.find('input[type="radio"]');
|
||||
let checkFormFields = [];
|
||||
for(let formField of targetFormFields){
|
||||
if(this.checked){
|
||||
if(formField.hasAttribute('data-default') || formField.getAttribute('data-default-value')){
|
||||
checkFormFields.push(formField);
|
||||
}
|
||||
}else{
|
||||
formField.setAttribute('data-default-value', formField.checked ? 'checked' : '');
|
||||
if(formField.hasAttribute('data-default')){
|
||||
checkFormFields.push(formField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let checkFormField of checkFormFields){
|
||||
checkFormField.checked = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('input[type="radio"]').on('change', function(){
|
||||
if(this.checked){
|
||||
let targetId = $(this).parents('fieldset').attr('data-id');
|
||||
$('input[type="checkbox"][data-target="' + targetId + '"]').prop('checked', true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* main init "admin" page
|
||||
*/
|
||||
$(() => {
|
||||
// set Dialog default config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// hide splash loading animation
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
setPageObserver();
|
||||
|
||||
let temp = $('.dataTable').dataTable({
|
||||
pageLength: 100,
|
||||
paging: true,
|
||||
ordering: true,
|
||||
autoWidth: false,
|
||||
hover: false,
|
||||
language: {
|
||||
emptyTable: 'No entries',
|
||||
zeroRecords: 'No entries found',
|
||||
lengthMenu: 'Show _MENU_ entries',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
|
||||
},
|
||||
data: null // use DOM data overwrites [] default -> data.loader.js
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
435
public/js/v1.5.2/app/conf/signature_type.js
Normal file
435
public/js/v1.5.2/app/conf/signature_type.js
Normal file
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* Created by exodus4d on 06.07.2015.
|
||||
* static signature types
|
||||
*
|
||||
* (*) marked fields are in-game verified and
|
||||
* proofed, signature names (copy & paste from scanning window)
|
||||
*/
|
||||
|
||||
define(['jquery'], ($) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
// signature sources
|
||||
// http://de.sistersprobe.wikia.com/wiki/EVE_Sister_Core_Scanner_Probe_Wiki
|
||||
|
||||
|
||||
// NullSec Relic sites, which can also spawn in C1, C2, C3 wormholes
|
||||
let nullSecRelicSites = {
|
||||
10: 'Ruined Angel Crystal Quarry',
|
||||
11: 'Ruined Angel Monument Site',
|
||||
12: 'Ruined Angel Science Outpost',
|
||||
13: 'Ruined Angel Temple Site',
|
||||
14: 'Ruined Blood Raider Crystal Quarry',
|
||||
15: 'Ruined Blood Raider Monument Site',
|
||||
16: 'Ruined Blood Raider Science Outpost',
|
||||
17: 'Ruined Blood Raider Temple Site',
|
||||
18: 'Ruined Guristas Crystal Quarry',
|
||||
19: 'Ruined Guristas Monument Site',
|
||||
20: 'Ruined Guristas Science Outpost',
|
||||
21: 'Ruined Guristas Temple Site',
|
||||
22: 'Ruined Sansha Crystal Quarry',
|
||||
23: 'Ruined Sansha Monument Site',
|
||||
24: 'Ruined Sansha Science Outpost',
|
||||
25: 'Ruined Sansha Temple Site',
|
||||
26: 'Ruined Serpentis Crystal Quarry',
|
||||
27: 'Ruined Serpentis Monument Site',
|
||||
28: 'Ruined Serpentis Science Outpost',
|
||||
29: 'Ruined Serpentis Temple Site'
|
||||
};
|
||||
|
||||
// NulSec Data sites, which can also spawn in C1, C2, C3 wormholes
|
||||
let nullSecDataSites = {
|
||||
10: 'Abandoned Research Complex DA005',
|
||||
11: 'Abandoned Research Complex DA015',
|
||||
12: 'Abandoned Research Complex DC007',
|
||||
13: 'Abandoned Research Complex DC021',
|
||||
14: 'Abandoned Research Complex DC035',
|
||||
15: 'Abandoned Research Complex DG003',
|
||||
16: 'Central Angel Command Center',
|
||||
17: 'Central Angel Data Mining Site',
|
||||
18: 'Central Angel Sparking Transmitter',
|
||||
19: 'Central Angel Survey Site',
|
||||
20: 'Central Blood Raider Command Center',
|
||||
21: 'Central Blood Raider Data Mining Site',
|
||||
22: 'Central Blood Raider Sparking Transmitter',
|
||||
23: 'Central Blood Raider Survey Site',
|
||||
24: 'Central Guristas Command Center',
|
||||
25: 'Central Guristas Data Mining Center',
|
||||
26: 'Central Guristas Sparking Transmitter',
|
||||
27: 'Central Guristas Survey Site',
|
||||
28: 'Central Sansha Command Center',
|
||||
29: 'Central Sansha Data Mining Site',
|
||||
30: 'Central Sansha Sparking Transmitter',
|
||||
31: 'Central Sansha Survey Site',
|
||||
32: 'Central Serpentis Command Center',
|
||||
33: 'Central Serpentis Data Mining Site',
|
||||
34: 'Central Serpentis Sparking Transmitter',
|
||||
35: 'Central Serpentis Survey Site'
|
||||
};
|
||||
|
||||
|
||||
// signature types
|
||||
let signatureTypes = {
|
||||
1: { // system type (wh)
|
||||
1: { // C1 (area id)
|
||||
1: { // Combat
|
||||
1: 'Perimeter Ambush Point',
|
||||
2: 'Perimeter Camp',
|
||||
3: 'Phase Catalyst Node',
|
||||
4: 'The Line'
|
||||
},
|
||||
2: $.extend({}, nullSecRelicSites, { // Relic
|
||||
1: 'Forgotten Perimeter Coronation Platform', //*
|
||||
2: 'Forgotten Perimeter Power Array' //*
|
||||
}),
|
||||
3: $.extend({}, nullSecDataSites, { // Data
|
||||
1: 'Unsecured Perimeter Amplifier', //*
|
||||
2: 'Unsecured Perimeter Information Center' //*
|
||||
}),
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// all k-space exits are static or K162
|
||||
1: 'H121 - C1',
|
||||
2: 'C125 - C2',
|
||||
3: 'O883 - C3',
|
||||
4: 'M609 - C4',
|
||||
5: 'L614 - C5',
|
||||
6: 'S804 - C6',
|
||||
7: 'F353 - C12 Thera'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Isolated Core Deposit', //*
|
||||
6: 'Uncommon Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
2: { // C2
|
||||
1: { // Combat
|
||||
1: 'Perimeter Checkpoint',
|
||||
2: 'Perimeter Hangar',
|
||||
3: 'The Ruins of Enclave Cohort 27',
|
||||
4: 'Sleeper Data Sanctuary'
|
||||
},
|
||||
2: $.extend({}, nullSecRelicSites, { // Relic
|
||||
1: 'Forgotten Perimeter Gateway', //*
|
||||
2: 'Forgotten Perimeter Habitation Coils' //*
|
||||
}),
|
||||
3: $.extend({}, nullSecDataSites, { // Data
|
||||
1: 'Unsecured Perimeter Comms Relay', //*
|
||||
2: 'Unsecured Perimeter Transponder Farm' //*
|
||||
}),
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// all w-space -> w-space are statics or K162
|
||||
1: 'Z647 - C1',
|
||||
2: 'D382 - C2',
|
||||
3: 'O477 - C3',
|
||||
4: 'Y683 - C4',
|
||||
5: 'N062 - C5',
|
||||
6: 'R474 - C6',
|
||||
7: 'F135 - C12 Thera'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Isolated Core Deposit', //*
|
||||
6: 'Uncommon Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
3: { // C3
|
||||
1: { // Combat
|
||||
1: 'Fortification Frontier Stronghold',
|
||||
2: 'Outpost Frontier Stronghold',
|
||||
3: 'Solar Cell',
|
||||
4: 'The Oruze Construct'
|
||||
},
|
||||
2: $.extend({}, nullSecRelicSites, { // Relic
|
||||
1: 'Forgotten Frontier Quarantine Outpost', //*
|
||||
2: 'Forgotten Frontier Recursive Depot' //*
|
||||
}),
|
||||
3: $.extend({}, nullSecDataSites, { // Data
|
||||
1: 'Unsecured Frontier Database', //*
|
||||
2: 'Unsecured Frontier Receiver' //*
|
||||
}),
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir', //*
|
||||
6: 'Bountiful Frontier Reservoir', //*
|
||||
7: 'Vast Frontier Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// all k-space exits are static or K162
|
||||
1: 'V301 - C1',
|
||||
2: 'I182 - C2',
|
||||
3: 'N968 - C3',
|
||||
4: 'T405 - C4',
|
||||
5: 'N770 - C5',
|
||||
6: 'A982 - C6',
|
||||
7: 'F135 - C12 Thera'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Infrequent Core Deposit', //*
|
||||
6: 'Unusual Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
4: { // C4
|
||||
1: { // Combat
|
||||
1: 'Frontier Barracks',
|
||||
2: 'Frontier Command Post',
|
||||
3: 'Integrated Terminus',
|
||||
4: 'Sleeper Information Sanctum'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Frontier Conversion Module',
|
||||
2: 'Forgotten Frontier Evacuation Center'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Frontier Digital Nexus',
|
||||
2: 'Unsecured Frontier Trinary Hub'
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir', //*
|
||||
6: 'Vast Frontier Reservoir', //*
|
||||
7: 'Bountiful Frontier Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// no *wandering* w-space -> w-space
|
||||
// all holes are statics or K162
|
||||
1: 'S047 - H',
|
||||
2: 'N290 - L',
|
||||
3: 'K329 - 0.0'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Unusual Core Deposit', //*
|
||||
6: 'Infrequent Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
5: { // C5
|
||||
1: { // Combat
|
||||
1: 'Core Garrison', //*
|
||||
2: 'Core Stronghold', //*
|
||||
3: 'Oruze Osobnyk', //*
|
||||
4: 'Quarantine Area'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Core Data Field',
|
||||
2: 'Forgotten Core Information Pen'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Frontier Enclave Relay',
|
||||
2: 'Unsecured Frontier Server Bank'
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Minor Perimeter Reservoir', //*
|
||||
3: 'Ordinary Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Token Perimeter Reservoir', //*
|
||||
6: 'Bountiful Frontier Reservoir', //*
|
||||
7: 'Vast Frontier Reservoir', //*
|
||||
8: 'Instrumental Core Reservoir', //*
|
||||
9: 'Vital Core Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'D792 - H',
|
||||
2: 'C140 - L',
|
||||
3: 'Z142 - 0.0'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Average Frontier Deposit', //*
|
||||
2: 'Unexceptional Frontier Deposit', //*
|
||||
3: 'Uncommon Core Deposit', //*
|
||||
4: 'Ordinary Perimeter Deposit', //*
|
||||
5: 'Common Perimeter Deposit', //*
|
||||
6: 'Exceptional Core Deposit', //*
|
||||
7: 'Infrequent Core Deposit', //*
|
||||
8: 'Unusual Core Deposit', //*
|
||||
9: 'Rarified Core Deposit', //*
|
||||
10: 'Isolated Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
6: { // C6
|
||||
1: { // Combat
|
||||
1: 'Core Citadel', //*
|
||||
2: 'Core Bastion', //*
|
||||
3: 'Strange Energy Readings', //*
|
||||
4: 'The Mirror' //*
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Core Assembly Hall', //*
|
||||
2: 'Forgotten Core Circuitry Disassembler' //*
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Core Backup Array', //*
|
||||
2: 'Unsecured Core Emergence' //*
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Minor Perimeter Reservoir', //*
|
||||
3: 'Ordinary Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Token Perimeter Reservoir', //*
|
||||
6: 'Bountiful Frontier Reservoir', //*
|
||||
7: 'Vast Frontier Reservoir', //*
|
||||
8: 'Instrumental Core Reservoir', //*
|
||||
9: 'Vital Core Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'B520 - H',
|
||||
2: 'D792 - H',
|
||||
3: 'C140 - L',
|
||||
4: 'C391 - L',
|
||||
5: 'C248 - 0.0',
|
||||
6: 'Z142 - 0.0'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Rarified Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
1: 'Superior Blood Raider Covert Research Facility' //*
|
||||
}
|
||||
},
|
||||
12: { // Thera wormhole
|
||||
1: { // Combat
|
||||
1: 'Epicenter',
|
||||
2: 'Expedition Command Outpost Wreck',
|
||||
3: 'Planetary Colonization Office Wreck',
|
||||
4: 'Testing Facilities'
|
||||
}
|
||||
},
|
||||
13: { // Shattered Wormholes
|
||||
5: { // Wormhole (some of them are static)
|
||||
1: 'P060 - C1',
|
||||
2: 'Z647 - C1',
|
||||
3: 'D382 - C2',
|
||||
4: 'L005 - C2',
|
||||
5: 'N766 - C2',
|
||||
6: 'C247 - C3',
|
||||
7: 'M267 - C3',
|
||||
8: 'O477 - C3',
|
||||
9: 'X877 - C4',
|
||||
10: 'Y683 - C4',
|
||||
11: 'H296 - C5',
|
||||
12: 'H900 - C5',
|
||||
13: 'H296 - C5',
|
||||
14: 'N062 - C5', // ??
|
||||
15: 'V911 - C5',
|
||||
16: 'U574 - C6',
|
||||
17: 'V753 - C6',
|
||||
18: 'W237 - C6',
|
||||
19: 'B274 - H',
|
||||
20: 'D792 - H',
|
||||
21: 'D845 - H',
|
||||
22: 'N110 - H',
|
||||
23: 'A239 - L',
|
||||
24: 'C391 - L',
|
||||
25: 'J244 - L',
|
||||
26: 'U201 - L', // ??
|
||||
27: 'U210 - L',
|
||||
28: 'C248 - 0.0',
|
||||
29: 'E545 - 0.0',
|
||||
30: 'K346 - 0.0',
|
||||
31: 'Z060 - 0.0'
|
||||
}
|
||||
}
|
||||
}, // system type (k-space)
|
||||
2: {
|
||||
30: { // High Sec
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
4: 'O128 - C4',
|
||||
5: 'M555 - C5',
|
||||
6: 'B041 - C6',
|
||||
7: 'A641 - H',
|
||||
8: 'R051 - L',
|
||||
9: 'V283 - 0.0',
|
||||
10: 'T458 - C12 Thera'
|
||||
}
|
||||
},
|
||||
31: { // Low Sec
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
4: 'O128 - C4',
|
||||
5: 'N432 - C5',
|
||||
6: 'U319 - C6',
|
||||
7: 'B449 - H',
|
||||
8: 'N944 - L',
|
||||
9: 'S199 - 0.0',
|
||||
10: 'M164 - C12 Thera'
|
||||
}
|
||||
},
|
||||
32: { // 0.0
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
4: 'O128 - C4',
|
||||
5: 'N432 - C5',
|
||||
6: 'U319 - C6',
|
||||
7: 'B449 - H',
|
||||
8: 'N944 - L',
|
||||
9: 'S199 - 0.0',
|
||||
10: 'L031 - C12 Thera'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return signatureTypes;
|
||||
});
|
||||
733
public/js/v1.5.2/app/conf/system_effect.js
Normal file
733
public/js/v1.5.2/app/conf/system_effect.js
Normal file
@@ -0,0 +1,733 @@
|
||||
/**
|
||||
* Created by exodus4d on 06.07.2015.
|
||||
* static system effects
|
||||
*/
|
||||
|
||||
|
||||
define([], function(){
|
||||
|
||||
'use strict';
|
||||
|
||||
// system effects
|
||||
let systemEffects = {
|
||||
wh: {
|
||||
magnetar: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Missile exp. radius',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Drone tracking',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Tracking speed',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Target Painter strength',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
redGiant: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Heat damage',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Overload bonus',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Smart Bomb range',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Smart Bomb damage',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Bomb damage',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
},
|
||||
pulsar: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Armor resist',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'NOS/Neut drain',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
},
|
||||
wolfRayet: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+60%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+88%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+116%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+144%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+172%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Shield resist',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Small Weapon damage',
|
||||
value: '+200%'
|
||||
},{
|
||||
effect: 'Signature size',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
cataclysmic: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
blackHole: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Missile exp. velocity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Stasis Webifier strength',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return systemEffects;
|
||||
});
|
||||
215
public/js/v1.5.2/app/console.js
Normal file
215
public/js/v1.5.2/app/console.js
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* Console module
|
||||
* -> extends default window.console log object
|
||||
*/
|
||||
|
||||
define([], () => {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* init custom window.console object
|
||||
* -> extend console obj with custom methods for styling and logging
|
||||
*/
|
||||
let initConsole = () => {
|
||||
|
||||
window.console = (origConsole => {
|
||||
// save orig methods for byPassing args to original methods
|
||||
let log = origConsole.log;
|
||||
let info = origConsole.info;
|
||||
let warn = origConsole.warn;
|
||||
let error = origConsole.error;
|
||||
|
||||
let styles = {
|
||||
'indentDefault': {
|
||||
'padding-left': '3px'
|
||||
},
|
||||
'global': {
|
||||
'font-weight': 500,
|
||||
'font-size': '11px',
|
||||
'line-height': '19px',
|
||||
'font-family': '"Fira Code", "Lucida Console"',
|
||||
},
|
||||
'ok': {
|
||||
'color': '#5cb85c'
|
||||
},
|
||||
'log': {
|
||||
'color': '#adadad'
|
||||
},
|
||||
'info': {
|
||||
'color': '#428bca'
|
||||
},
|
||||
'warn': {
|
||||
'color': '#ffdd9e'
|
||||
},
|
||||
'error': {
|
||||
'color': '#ff8080'
|
||||
},
|
||||
'pf': {
|
||||
'color': '#568a89'
|
||||
},
|
||||
'brand': {
|
||||
'color': '#375959',
|
||||
'line-height': '35px',
|
||||
'font-size': '25px'
|
||||
}
|
||||
};
|
||||
|
||||
let placeholders = {
|
||||
'%s': {
|
||||
'style': ['color: #e93f3b; font-style: italic', 'color: inherit']
|
||||
},
|
||||
'%i': {
|
||||
'style': ['color: #9980ff', 'color: inherit'],
|
||||
},
|
||||
'%d': {
|
||||
'style': ['color: #9980ff', 'color: inherit']
|
||||
},
|
||||
'%f': {
|
||||
'style': ['color: #9980ff', 'color: inherit']
|
||||
},
|
||||
'%o': {
|
||||
'style': ['', '']
|
||||
},
|
||||
'%O': {
|
||||
'style': ['', '']
|
||||
}
|
||||
};
|
||||
|
||||
let findPlaceholders = str => {
|
||||
let exp = new RegExp(Object.keys(placeholders).join('|'), 'g');
|
||||
let matches = str.match(exp);
|
||||
return matches ? matches : [];
|
||||
};
|
||||
|
||||
let addStylePlaceholder = str => {
|
||||
let exp = new RegExp(Object.keys(placeholders).join('|'), 'g');
|
||||
|
||||
return str.replace(exp, function(matched){
|
||||
return '%c' + matched + '%c';
|
||||
});
|
||||
};
|
||||
|
||||
let getStyleByPlaceholder = (placeholder, clear = false) => {
|
||||
let css = '';
|
||||
if(placeholders.hasOwnProperty(placeholder)){
|
||||
css = placeholders[placeholder].style[clear ? 1 : 0];
|
||||
}
|
||||
return css;
|
||||
};
|
||||
|
||||
let getStyleByLogType = (logType, props = []) => {
|
||||
let css = '';
|
||||
if(styles.hasOwnProperty(logType)){
|
||||
css = Object.keys(styles[logType])
|
||||
.filter(prop => props.length ? props.includes(prop) : true)
|
||||
.reduce((css, prop,i, affe) => {
|
||||
css += prop + ':' + styles[logType][prop] + ';';
|
||||
return css;
|
||||
}, '');
|
||||
}
|
||||
return css;
|
||||
};
|
||||
|
||||
let setLineStyleByLogType = (logType, args) => {
|
||||
if(args.length){
|
||||
let lineStyle = getStyleByLogType('global') + getStyleByLogType(logType);
|
||||
lineStyle += ['ok', 'log', 'info', 'pf'].includes(logType) ? getStyleByLogType('indentDefault') : '';
|
||||
let bullet = ['ok', 'log', 'info', 'pf'].includes(logType) ? '●' : '';
|
||||
|
||||
if(typeof args[0] === 'string'){
|
||||
// prepend placeholder to existing message
|
||||
args[0] = '%c' + bullet + ' ' + args[0];
|
||||
}else{
|
||||
// prepend placeholder as new message
|
||||
args.splice(0, 0, '%c' + bullet + ' ' + logType + ':');
|
||||
}
|
||||
// set line style as 2nd argument
|
||||
args.splice(1, 0, lineStyle);
|
||||
}
|
||||
};
|
||||
|
||||
let setMessageStyleByLogType = (logType, args) => {
|
||||
if(typeof args[0] === 'string') {
|
||||
let placeholdersFound = findPlaceholders(args[0]);
|
||||
let placeholderCount = placeholdersFound.length;
|
||||
|
||||
// add c% placeholders around other placeholders
|
||||
args[0] = addStylePlaceholder(args[0]);
|
||||
|
||||
// add style args for c% placeholders
|
||||
let placeholderIndex = 0;
|
||||
let argIndexStart = 1;
|
||||
let argIndexEnd = argIndexStart + placeholderCount;
|
||||
let argIndexOffset = 0;
|
||||
for (let argIndex = argIndexStart; argIndex < argIndexEnd; argIndex++) {
|
||||
args.splice(argIndex + argIndexOffset, 0, getStyleByPlaceholder(placeholdersFound[placeholderIndex]));
|
||||
argIndexOffset += 2;
|
||||
args.splice(argIndex + argIndexOffset, 0, getStyleByPlaceholder(placeholdersFound[placeholderIndex], true) + ';' + getStyleByLogType('global') + getStyleByLogType(logType));
|
||||
placeholderIndex++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
origConsole.ok = (...args) => {
|
||||
setMessageStyleByLogType('ok', args);
|
||||
setLineStyleByLogType('ok', args);
|
||||
info.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.info = (...args) => {
|
||||
setMessageStyleByLogType('info', args);
|
||||
setLineStyleByLogType('info', args);
|
||||
info.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.log = (...args) => {
|
||||
setMessageStyleByLogType('log', args);
|
||||
setLineStyleByLogType('log', args);
|
||||
log.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.warn = (...args) => {
|
||||
setMessageStyleByLogType('warn', args);
|
||||
setLineStyleByLogType('warn', args);
|
||||
warn.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.error = (...args) => {
|
||||
setMessageStyleByLogType('error', args);
|
||||
setLineStyleByLogType('error', args);
|
||||
error.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.pf = (...args) => {
|
||||
setMessageStyleByLogType('pf', args);
|
||||
setLineStyleByLogType('pf', args);
|
||||
info.apply(origConsole, args);
|
||||
};
|
||||
|
||||
origConsole.brand = (...args) => {
|
||||
setMessageStyleByLogType('brand', args);
|
||||
setLineStyleByLogType('brand', args);
|
||||
info.apply(origConsole, args);
|
||||
};
|
||||
|
||||
return origConsole;
|
||||
})(window.console);
|
||||
};
|
||||
|
||||
initConsole();
|
||||
|
||||
/**
|
||||
* show current program version information console
|
||||
* @param version
|
||||
*/
|
||||
let showVersionInfo = (version) => {
|
||||
console.ok('%c PATHFINDER',
|
||||
'color: #477372; font-size: 25px; margin-left: 10px; line-height: 100px; text-shadow: 1px 1px 0 #212C30; ' +
|
||||
'background: url(https://i.imgur.com/1Gw8mjL.png) no-repeat;');
|
||||
console.pf('Release: %s', version);
|
||||
};
|
||||
|
||||
return {
|
||||
showVersionInfo: showVersionInfo
|
||||
};
|
||||
});
|
||||
160
public/js/v1.5.2/app/counter.js
Normal file
160
public/js/v1.5.2/app/counter.js
Normal file
@@ -0,0 +1,160 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util'
|
||||
], ($, Init, Util) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
counterDigitSmallClass: 'pf-digit-counter-small',
|
||||
counterDigitLargeClass: 'pf-digit-counter-large'
|
||||
};
|
||||
|
||||
/**
|
||||
* update element with time information
|
||||
* @param element
|
||||
* @param tempDate
|
||||
* @param round
|
||||
*/
|
||||
let updateDateDiff = (element, tempDate, round) => {
|
||||
let diff = Util.getTimeDiffParts(tempDate, new Date());
|
||||
let days = diff.days;
|
||||
let hrs = diff.hours;
|
||||
let min = diff.min;
|
||||
let leftSec = diff.sec;
|
||||
let parts = [];
|
||||
|
||||
if(
|
||||
round === 'd' &&
|
||||
days >= 1
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitLargeClass + '">' + '> 1d' + '</span>');
|
||||
}else{
|
||||
if(
|
||||
days > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitLargeClass + '">' + days + 'd' + '</span>');
|
||||
}
|
||||
if(
|
||||
hrs > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + hrs + 'h' + '</span>');
|
||||
}
|
||||
if(
|
||||
min > 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + min + 'm' + '</span>');
|
||||
}
|
||||
|
||||
if(
|
||||
leftSec >= 0 ||
|
||||
parts.length > 0
|
||||
){
|
||||
parts.push('<span class="' + config.counterDigitSmallClass + '">' + leftSec + 's' + '</span>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
element.html(parts.join(' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* destroy all active counter recursive
|
||||
*/
|
||||
$.fn.destroyTimestampCounter = function(recursive){
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
let counterSelector = '[data-counter="init"]';
|
||||
let counterElements = element.filter(counterSelector);
|
||||
if(recursive){
|
||||
counterElements = counterElements.add(element.find(counterSelector));
|
||||
}
|
||||
|
||||
counterElements.each(function(){
|
||||
let element = $(this);
|
||||
let interval = element.data('interval');
|
||||
if(interval){
|
||||
clearInterval(interval);
|
||||
element.removeAttr('data-counter').removeData('interval').removeClass('stopCounter');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init a live counter based on a unix timestamp
|
||||
* @param round string e.g. 'd' => round days
|
||||
*/
|
||||
$.fn.initTimestampCounter = function(round){
|
||||
return this.each(function(){
|
||||
let element = $(this);
|
||||
let timestamp = parseInt( element.text() );
|
||||
|
||||
// do not init twice
|
||||
if(timestamp > 0){
|
||||
// mark as init
|
||||
element.attr('data-counter', 'init');
|
||||
|
||||
let date = new Date( timestamp * 1000);
|
||||
|
||||
updateDateDiff(element, date, round);
|
||||
|
||||
// show element (if invisible) after first update
|
||||
element.css({'visibility': 'initial'});
|
||||
|
||||
// calc ms until next second
|
||||
// -> makes sure all counter update in sync no matter when init
|
||||
let msUntilSecond = 1500 - new Date().getMilliseconds();
|
||||
setTimeout(function(){
|
||||
let refreshIntervalId = window.setInterval(function(){
|
||||
|
||||
// update element with current time
|
||||
if( !element.hasClass('stopCounter')){
|
||||
updateDateDiff(element, date, round);
|
||||
}else{
|
||||
clearInterval( element.data('interval') );
|
||||
}
|
||||
}, 500);
|
||||
|
||||
element.data('interval', refreshIntervalId);
|
||||
}, msUntilSecond);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init global timestamp counter or DataTable for specific columns
|
||||
* @param tableElement
|
||||
* @param columnSelector
|
||||
* @param round
|
||||
*/
|
||||
let initTableCounter = (tableElement, columnSelector, round) => {
|
||||
let tableApi = tableElement.api();
|
||||
|
||||
// mark as init
|
||||
tableElement.attr('data-counter', 'init');
|
||||
let refreshIntervalId = window.setInterval(() => {
|
||||
tableApi.cells(null, columnSelector).every(function(rowIndex, colIndex, tableLoopCount, cellLoopCount){
|
||||
let cell = this;
|
||||
let node = cell.node();
|
||||
let data = cell.data();
|
||||
if(data && Number.isInteger(data) && !node.classList.contains('stopCounter')){
|
||||
// timestamp expected int > 0
|
||||
let date = new Date(data * 1000);
|
||||
updateDateDiff( cell.nodes().to$(), date, round);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
tableElement.data('interval', refreshIntervalId);
|
||||
};
|
||||
|
||||
return {
|
||||
updateDateDiff: updateDateDiff,
|
||||
initTableCounter: initTableCounter
|
||||
};
|
||||
});
|
||||
161
public/js/v1.5.2/app/datatables.loader.js
Normal file
161
public/js/v1.5.2/app/datatables.loader.js
Normal file
@@ -0,0 +1,161 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/promises/promise.deferred',
|
||||
'app/promises/promise.timeout',
|
||||
'datatables.net',
|
||||
'datatables.net-buttons',
|
||||
'datatables.net-buttons-html',
|
||||
'datatables.net-responsive',
|
||||
'datatables.net-select'
|
||||
], ($, Init, DeferredPromise, TimeoutPromise) => {
|
||||
'use strict';
|
||||
|
||||
// all Datatables stuff is available...
|
||||
let initDefaultDatatablesConfig = () => {
|
||||
|
||||
$.extend(true, $.fn.dataTable.defaults, {
|
||||
pageLength: -1,
|
||||
pagingType: 'simple_numbers',
|
||||
lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
|
||||
order: [], // no default order because columnDefs is empty
|
||||
autoWidth: false,
|
||||
language: {
|
||||
info: '_START_ - _END_ of _TOTAL_ entries'
|
||||
},
|
||||
responsive: {
|
||||
breakpoints: Init.breakpoints,
|
||||
details: false
|
||||
},
|
||||
columnDefs: [],
|
||||
data: []
|
||||
});
|
||||
|
||||
// global open event
|
||||
$(document).on('destroy.dt', '.dataTable ', function(e, settings){
|
||||
let table = $(this);
|
||||
let tableApi = new $.fn.dataTable.Api(settings);
|
||||
// end all active processes (e.g. table lock)
|
||||
// -> this custom extension is only available if "StatusTable" feature is enabled with it
|
||||
if(typeof tableApi.endProcesses === 'function'){
|
||||
tableApi.endProcesses();
|
||||
}
|
||||
|
||||
// remove all active counters in table
|
||||
table.destroyTimestampCounter(true);
|
||||
});
|
||||
|
||||
let StatusTable = function(settings){
|
||||
let me = this;
|
||||
me.statusContainer = $('<div>', {
|
||||
class: 'dt-stats pull-right'
|
||||
});
|
||||
|
||||
me.statusLock = $('<span>', {
|
||||
class: ['dt-stat', 'disabled', 'fade'].join(' ')
|
||||
}).append($('<i>', {class: ['fas', 'fa-fw', 'fa-lock'].join(' ')}));
|
||||
|
||||
me.statusRequest = $('<span>', {
|
||||
class: ['dt-stat', 'disabled', 'fade'].join(' ')
|
||||
}).append($('<i>', {class: ['fas', 'fa-fw', 'fa-sync', 'fa-spin'].join(' ')}));
|
||||
|
||||
me.statusContainer.append(me.statusLock, me.statusRequest);
|
||||
|
||||
// processStore holds "unfulfilled" promises
|
||||
me.processStore = {};
|
||||
me.defaultProcessName = 'default';
|
||||
|
||||
me.lock = () => me.statusLock.addClass('in');
|
||||
me.unlock = () => me.statusLock.removeClass('in');
|
||||
me.request = () => me.statusRequest.addClass('in');
|
||||
me.unrequest = () => me.statusRequest.removeClass('in');
|
||||
|
||||
me.endProcess = deferredPromise => {
|
||||
me.processStore[deferredPromise.data.name].delete(deferredPromise);
|
||||
// update table processStatus
|
||||
me.updateProcessStatus(deferredPromise.data.name);
|
||||
};
|
||||
|
||||
me.hasProcesses = name => {
|
||||
let hasProcesses = false;
|
||||
if(me.processStore[name] instanceof Map){
|
||||
hasProcesses = me.processStore[name].size > 0;
|
||||
}
|
||||
return hasProcesses;
|
||||
};
|
||||
|
||||
me.updateProcessStatus = name => {
|
||||
let method = me.hasProcesses(name) ? name : 'un' + name;
|
||||
me[method]();
|
||||
};
|
||||
|
||||
$.fn.dataTable.Api.register('newProcess()', function(name = me.defaultProcessName){
|
||||
// new DeferredPromise for process
|
||||
let deferredPromise = new DeferredPromise();
|
||||
deferredPromise.data = {name: name};
|
||||
|
||||
// reject DeferredPromise after timeout (if not resolved
|
||||
let timeoutPromise = new TimeoutPromise(deferredPromise);
|
||||
timeoutPromise
|
||||
.then(function(name, payload){
|
||||
// resolved within timeout -> wait for finally() block
|
||||
}.bind(me, name))
|
||||
.catch(error => {
|
||||
if(error instanceof Error){
|
||||
// either timeout error or error from rejected deferredPromise
|
||||
console.warn(error);
|
||||
}
|
||||
})
|
||||
.finally(function(deferredPromise){
|
||||
// no matter if TimeoutPromise is resolved or rejected
|
||||
// -> remove from processStore
|
||||
this.endProcess(deferredPromise);
|
||||
}.bind(me, deferredPromise));
|
||||
|
||||
// store TimeoutPromise -------------------------------------------------------------------------------
|
||||
if(!(me.processStore[name] instanceof Map)){
|
||||
me.processStore[name] = new Map();
|
||||
}
|
||||
me.processStore[name].set(deferredPromise);
|
||||
|
||||
// update table processStatus
|
||||
me.updateProcessStatus(name);
|
||||
|
||||
return deferredPromise;
|
||||
});
|
||||
|
||||
$.fn.dataTable.Api.register('hasProcesses()', function(name = me.defaultProcessName){
|
||||
return me.hasProcesses(name);
|
||||
});
|
||||
|
||||
$.fn.dataTable.Api.register('endProcess()', function(deferredPromise){
|
||||
me.endProcess(deferredPromise);
|
||||
deferredPromise.resolve();
|
||||
});
|
||||
|
||||
$.fn.dataTable.Api.register('endProcesses()', function(){
|
||||
for(let [name, store] of Object.entries(me.processStore)){
|
||||
for(let [deferredPromise, value] of store.entries()){
|
||||
me.endProcess(deferredPromise);
|
||||
deferredPromise.resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
StatusTable.prototype.getContainer = function(){
|
||||
return this.statusContainer;
|
||||
};
|
||||
|
||||
$.fn.dataTable.ext.feature.push({
|
||||
fnInit: settings => {
|
||||
let oStatusTable = new StatusTable(settings);
|
||||
return oStatusTable.getContainer();
|
||||
},
|
||||
cFeature: 'S',
|
||||
sFeature: 'StatusTable'
|
||||
});
|
||||
};
|
||||
|
||||
initDefaultDatatablesConfig();
|
||||
});
|
||||
557
public/js/v1.5.2/app/init.js
Normal file
557
public/js/v1.5.2/app/init.js
Normal file
@@ -0,0 +1,557 @@
|
||||
/**
|
||||
* Init
|
||||
*/
|
||||
|
||||
define(['jquery'], ($) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
let Config = {
|
||||
path: {
|
||||
img: '/public/img/', // path for images
|
||||
api: '/api/rest', //ajax URL - REST API
|
||||
// user API
|
||||
getCaptcha: '/api/user/getCaptcha', // ajax URL - get captcha image
|
||||
getServerStatus: '/api/user/getEveServerStatus', // ajax URL - get EVE-Online server status
|
||||
getCookieCharacterData: '/api/user/getCookieCharacter', // ajax URL - get character data from cookie
|
||||
logIn: '/api/user/logIn', // ajax URL - login
|
||||
logout: '/api/user/logout', // ajax URL - logout
|
||||
deleteLog: '/api/user/deleteLog', // ajax URL - delete character log
|
||||
openIngameWindow: '/api/user/openIngameWindow', // ajax URL - open inGame Window
|
||||
saveUserConfig: '/api/user/saveAccount', // ajax URL - saves/update user account
|
||||
deleteAccount: '/api/user/deleteAccount', // ajax URL - delete Account data
|
||||
// access API
|
||||
searchAccess: '/api/access/search', // ajax URL - search user/corporation/ally by name
|
||||
// main config/map ping API
|
||||
initData: '/api/map/initData', // ajax URL - get static configuration 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
|
||||
saveMap: '/api/map/save', // ajax URL - save/update map
|
||||
deleteMap: '/api/map/delete', // ajax URL - delete map
|
||||
importMap: '/api/map/import', // ajax URL - import map
|
||||
getMapConnectionData: '/api/map/getConnectionData', // ajax URL - get connection data
|
||||
getMapLogData: '/api/map/getLogData', // ajax URL - get logs data
|
||||
// system API
|
||||
getSystemGraphData: '/api/system/graphData', // ajax URL - get all system graph data
|
||||
setDestination: '/api/system/setDestination', // ajax URL - set destination
|
||||
pokeRally: '/api/system/pokeRally', // ajax URL - send rally point pokes
|
||||
// route API
|
||||
searchRoute: '/api/route/search', // ajax URL - search system routes
|
||||
// stats API
|
||||
getStatisticsData: '/api/statistic/getData', // ajax URL - get statistics data (activity log)
|
||||
// universe API
|
||||
searchUniverseData: '/api/universe/search', // ajax URL - search universe data by category Ids
|
||||
searchUniverseSystemData: '/api/universe/systems', // ajax URL - search universe system data by name
|
||||
getConstellationData: '/api/universe/constellationData', // ajax URL - get system constellation data
|
||||
// GitHub API
|
||||
gitHubReleases: '/api/github/releases' // ajax URL - get release info from GitHub
|
||||
},
|
||||
breakpoints: [
|
||||
{ name: 'screen-xl', width: Infinity },
|
||||
{ name: 'screen-l', width: 1600 },
|
||||
{ name: 'screen-m', width: 1200 },
|
||||
{ name: 'screen-d', width: 1000 },
|
||||
{ name: 'screen-s', width: 780 },
|
||||
{ name: 'screen-xs', width: 480 }
|
||||
],
|
||||
animationSpeed: {
|
||||
splashOverlay: 300, // "splash" loading overlay
|
||||
headerLink: 100, // links in head bar
|
||||
mapOverlay: 200, // show/hide duration for map overlays
|
||||
mapOverlayLocal: 180, // show/hide duration for map "local" overlay
|
||||
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',
|
||||
label: 'desktop',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-space-shuttle',
|
||||
label: 'space shuttle',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-anchor',
|
||||
label: 'anchor',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-fire',
|
||||
label: 'fire',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-bookmark',
|
||||
label: 'bookmark',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-cube',
|
||||
label: 'cube',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-star',
|
||||
label: 'star',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-plane',
|
||||
label: 'plane',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-globe',
|
||||
label: 'globe',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-rocket',
|
||||
label: 'rocket',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-life-ring',
|
||||
label: 'life ring',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-heart',
|
||||
label: 'heart',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-poop',
|
||||
label: 'poop',
|
||||
unicode: ''
|
||||
}
|
||||
],
|
||||
|
||||
classes: {
|
||||
// log types
|
||||
logTypes: {
|
||||
info: {
|
||||
class: 'pf-log-info',
|
||||
label: 'info'
|
||||
},
|
||||
warning: {
|
||||
class: 'pf-log-warning',
|
||||
label: 'warning'
|
||||
},
|
||||
error: {
|
||||
class: 'pf-log-error',
|
||||
label: 'error'
|
||||
}
|
||||
},
|
||||
// system effects
|
||||
systemEffects: {
|
||||
effect: {
|
||||
class: 'pf-system-effect',
|
||||
name: 'no effect'
|
||||
},
|
||||
magnetar: {
|
||||
class: 'pf-system-effect-magnetar',
|
||||
name: 'magnetar'
|
||||
},
|
||||
redGiant: {
|
||||
class: 'pf-system-effect-redgiant',
|
||||
name: 'red giant'
|
||||
},
|
||||
pulsar: {
|
||||
class: 'pf-system-effect-pulsar',
|
||||
name: 'pulsar'
|
||||
},
|
||||
wolfRayet: {
|
||||
class: 'pf-system-effect-wolfrayet',
|
||||
name: 'wolf rayet'
|
||||
},
|
||||
cataclysmic: {
|
||||
class: 'pf-system-effect-cataclysmic',
|
||||
name: 'cataclysmic'
|
||||
},
|
||||
blackHole: {
|
||||
class: 'pf-system-effect-blackhole',
|
||||
name: 'black hole'
|
||||
}
|
||||
},
|
||||
// system security
|
||||
systemSecurity: {
|
||||
'security': {
|
||||
class: 'pf-system-sec'
|
||||
},
|
||||
'A': {
|
||||
class: 'pf-system-sec-abyssal'
|
||||
},
|
||||
'SH': {
|
||||
class: 'pf-system-sec-unknown'
|
||||
},
|
||||
'H': {
|
||||
class: 'pf-system-sec-highSec'
|
||||
},
|
||||
'L': {
|
||||
class: 'pf-system-sec-lowSec'
|
||||
},
|
||||
'0.0': {
|
||||
class: 'pf-system-sec-nullSec'
|
||||
},
|
||||
'C1': {
|
||||
class: 'pf-system-sec-low'
|
||||
},
|
||||
'C2': {
|
||||
class: 'pf-system-sec-low'
|
||||
},
|
||||
'C3': {
|
||||
class: 'pf-system-sec-mid'
|
||||
},
|
||||
'C4': {
|
||||
class: 'pf-system-sec-mid'
|
||||
},
|
||||
'C5': {
|
||||
class: 'pf-system-sec-high'
|
||||
},
|
||||
'C6': {
|
||||
class: 'pf-system-sec-high'
|
||||
},
|
||||
'C12': {
|
||||
class: 'pf-system-sec-special'
|
||||
}
|
||||
},
|
||||
// true sec
|
||||
trueSec: {
|
||||
'0.0': {
|
||||
class: 'pf-system-security-0-0'
|
||||
},
|
||||
'0.1': {
|
||||
class: 'pf-system-security-0-1'
|
||||
},
|
||||
'0.2': {
|
||||
class: 'pf-system-security-0-2'
|
||||
},
|
||||
'0.3': {
|
||||
class: 'pf-system-security-0-3'
|
||||
},
|
||||
'0.4': {
|
||||
class: 'pf-system-security-0-4'
|
||||
},
|
||||
'0.5': {
|
||||
class: 'pf-system-security-0-5'
|
||||
},
|
||||
'0.6': {
|
||||
class: 'pf-system-security-0-6'
|
||||
},
|
||||
'0.7': {
|
||||
class: 'pf-system-security-0-7'
|
||||
},
|
||||
'0.8': {
|
||||
class: 'pf-system-security-0-8'
|
||||
},
|
||||
'0.9': {
|
||||
class: 'pf-system-security-0-9'
|
||||
},
|
||||
'1.0': {
|
||||
class: 'pf-system-security-1-0'
|
||||
}
|
||||
},
|
||||
// system info
|
||||
systemInfo: {
|
||||
rally: {
|
||||
class: 'pf-system-info-rally',
|
||||
label: 'rally point'
|
||||
}
|
||||
},
|
||||
// planets
|
||||
planets: {
|
||||
barren: {
|
||||
class: 'pf-planet-barren'
|
||||
},
|
||||
gas: {
|
||||
class: 'pf-planet-gas'
|
||||
},
|
||||
ice: {
|
||||
class: 'pf-planet-ice'
|
||||
},
|
||||
lava: {
|
||||
class: 'pf-planet-lava'
|
||||
},
|
||||
oceanic: {
|
||||
class: 'pf-planet-oceanic'
|
||||
},
|
||||
plasma: {
|
||||
class: 'pf-planet-plasma'
|
||||
},
|
||||
shattered: {
|
||||
class: 'pf-planet-shattered'
|
||||
},
|
||||
storm: {
|
||||
class: 'pf-planet-storm'
|
||||
},
|
||||
temperate: {
|
||||
class: 'pf-planet-temperate'
|
||||
}
|
||||
},
|
||||
// easy-pie-charts
|
||||
pieChart: {
|
||||
class: 'pf-pie-chart', // class for all pie charts
|
||||
pieChartMapCounterClass: 'pf-pie-chart-map-timer' // class for timer chart
|
||||
}
|
||||
},
|
||||
// map scopes
|
||||
defaultMapScope: 'wh', // default scope for connection
|
||||
// map endpoint types
|
||||
endpointTypes: {
|
||||
bubble: {
|
||||
cssClass: 'pf-map-endpoint-bubble',
|
||||
}
|
||||
},
|
||||
// map connection types
|
||||
connectionTypes: {
|
||||
abyssal: {
|
||||
cssClass: 'pf-map-connection-abyssal',
|
||||
paintStyle: {
|
||||
dashstyle: '0.5 2' // dotted line
|
||||
}
|
||||
},
|
||||
jumpbridge: {
|
||||
cssClass: 'pf-map-connection-jumpbridge',
|
||||
paintStyle: {
|
||||
dashstyle: '4 2 1 2'
|
||||
}
|
||||
},
|
||||
stargate: {
|
||||
cssClass: 'pf-map-connection-stargate',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_eol: {
|
||||
cssClass: 'pf-map-connection-wh-eol',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_fresh: {
|
||||
cssClass: 'pf-map-connection-wh-fresh',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_reduced: {
|
||||
cssClass: 'pf-map-connection-wh-reduced',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_critical: {
|
||||
cssClass: 'pf-map-connection-wh-critical',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
frigate: {
|
||||
cssClass: 'pf-map-connection-frig',
|
||||
paintStyle: {
|
||||
dashstyle: '0.99'
|
||||
},
|
||||
overlays:[
|
||||
['Label',
|
||||
{
|
||||
label: 'frig',
|
||||
cssClass: ['pf-map-component-overlay', 'frig'].join(' '),
|
||||
location: 0.6
|
||||
}]
|
||||
]
|
||||
},
|
||||
preserve_mass: {
|
||||
cssClass: 'pf-map-connection-preserve-mass',
|
||||
overlays:[
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-fw fa-exclamation-triangle"></i> save mass',
|
||||
cssClass: ['pf-map-component-overlay', 'mass'].join(' '),
|
||||
location: 0.6
|
||||
}]
|
||||
]
|
||||
},
|
||||
state_active: {
|
||||
cssClass: 'pf-map-connection-active'
|
||||
},
|
||||
state_process: {
|
||||
cssClass: 'pf-map-connection-process',
|
||||
overlays:[
|
||||
['Label',
|
||||
{
|
||||
label: '<i class="fas fa-fw fa-sync fa-spin"></i>',
|
||||
cssClass: ['pf-map-connection-state-overlay'].join(' '),
|
||||
location: 0.6
|
||||
}]
|
||||
]
|
||||
}
|
||||
},
|
||||
// signature groups
|
||||
signatureGroups: {
|
||||
1: {
|
||||
name: '(combat site|kampfgebiet|site de combat|Боевой район)', //*
|
||||
label: 'Combat'
|
||||
},
|
||||
2: {
|
||||
name: '(relic site|reliktgebiet|site de reliques|Археологический район)', //*
|
||||
label: 'Relic'
|
||||
},
|
||||
3: {
|
||||
name: '(data site|datengebiet|site de données|Информационный район)',
|
||||
label: 'Data'
|
||||
},
|
||||
4: {
|
||||
name: '(gas site|gasgebiet|site de collecte de gaz|Газовый район)',
|
||||
label: 'Gas'
|
||||
},
|
||||
5: {
|
||||
name: '(wormhole|wurmloch|trou de ver|Червоточина)',
|
||||
label: 'Wormhole'
|
||||
},
|
||||
6: {
|
||||
name: '(ore site|mineraliengebiet|site de minerai|Астероидный район)',
|
||||
label: 'Ore'
|
||||
},
|
||||
7: {
|
||||
name: '(ghost|Призрачный)',
|
||||
label: 'Ghost'
|
||||
}
|
||||
},
|
||||
// frigate wormholes
|
||||
frigateWormholes: {
|
||||
1: { // C1
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
2: { // C2
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
3: { // C3
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
4: { // C4
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
5: { // C5
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
6: { // C6
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
13: { // Shattered Wormholes (some of them are static)
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
30: { // High Sec
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
31: { // Low Sec
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
},
|
||||
32: { // 0.0
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - 0.0',
|
||||
8: 'A009 - C13'
|
||||
}
|
||||
},
|
||||
// incoming wormholes
|
||||
incomingWormholes: {
|
||||
1: 'K162 - C1/2/3 (unknown)',
|
||||
2: 'K162 - C4/5 (dangerous)',
|
||||
3: 'K162 - C6 (deadly)',
|
||||
4: 'K162 - H',
|
||||
5: 'K162 - L',
|
||||
6: 'K162 - 0.0',
|
||||
7: 'K162 - C12 Thera'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return Config;
|
||||
});
|
||||
465
public/js/v1.5.2/app/key.js
Normal file
465
public/js/v1.5.2/app/key.js
Normal file
@@ -0,0 +1,465 @@
|
||||
define([
|
||||
'jquery'
|
||||
], ($) => {
|
||||
'use strict';
|
||||
|
||||
let allCombo = {
|
||||
// global -------------------------------------------------------------------------------------------
|
||||
tabReload: {
|
||||
group: 'global',
|
||||
label: 'Close open dialog',
|
||||
keyNames: ['ESC']
|
||||
},
|
||||
// signature ----------------------------------------------------------------------------------------
|
||||
signatureSelect: {
|
||||
group: 'signatures',
|
||||
label: 'Select multiple rows',
|
||||
keyNames: ['CONTROL', 'CLICK']
|
||||
},
|
||||
signatureNavigate: {
|
||||
group: 'signatures',
|
||||
label: 'Table navigation',
|
||||
keyNames: ['UP', 'RIGHT', 'DOWN', 'LEFT'],
|
||||
list: true
|
||||
}
|
||||
};
|
||||
|
||||
let allEvents = {
|
||||
// global -------------------------------------------------------------------------------------------
|
||||
tabReload: {
|
||||
group: 'global',
|
||||
label: 'Reload tab',
|
||||
keyNames: ['CONTROL', 'R']
|
||||
},
|
||||
clipboardPaste: {
|
||||
group: 'global',
|
||||
label: 'Update signatures/D-Scan from clipboard',
|
||||
keyNames: ['CONTROL', 'V'],
|
||||
alias: 'paste'
|
||||
},
|
||||
newSignature: {
|
||||
group: 'signatures',
|
||||
label: 'New Signature',
|
||||
keyNames: ['ALT', '3']
|
||||
},
|
||||
|
||||
// map ----------------------------------------------------------------------------------------------
|
||||
mapSystemAdd: {
|
||||
group: 'map',
|
||||
label: 'New system',
|
||||
keyNames: ['ALT', '2']
|
||||
},
|
||||
mapSystemsSelect: {
|
||||
group: 'map',
|
||||
label: 'Select all systems',
|
||||
keyNames: ['CONTROL', 'A']
|
||||
},
|
||||
mapSystemsDelete: {
|
||||
group: 'map',
|
||||
label: 'Delete selected systems',
|
||||
keyNames: ['CONTROL', 'D']
|
||||
}
|
||||
};
|
||||
|
||||
let groups = {
|
||||
global: {
|
||||
label: 'Global'
|
||||
},
|
||||
map: {
|
||||
label: 'Map'
|
||||
},
|
||||
signatures: {
|
||||
label: 'Signature'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* enables some debug output in console
|
||||
* @type {boolean}
|
||||
*/
|
||||
let debug = false;
|
||||
|
||||
/**
|
||||
* check interval for "new" active keys
|
||||
* @type {number}
|
||||
*/
|
||||
let keyWatchPeriod = 100;
|
||||
|
||||
/**
|
||||
* DOM data key for an element that lists all active events (comma separated)
|
||||
* @type {string}
|
||||
*/
|
||||
let dataKeyEvents = 'key-events';
|
||||
|
||||
/**
|
||||
* DOM data key prefix whether domElement that holds the trigger needs to be "focused"
|
||||
* @type {string}
|
||||
*/
|
||||
let dataKeyFocusPrefix = 'key-focus-';
|
||||
|
||||
/**
|
||||
* DOM data key that holds the callback function for that element
|
||||
* @type {string}
|
||||
*/
|
||||
let dataKeyCallbackPrefix = 'key-callback-';
|
||||
|
||||
/**
|
||||
* check if module is initiated
|
||||
*/
|
||||
let isInit = false;
|
||||
|
||||
/**
|
||||
* global key map holds all active (hold down) keys
|
||||
* @type {{}}
|
||||
*/
|
||||
let map = {};
|
||||
|
||||
/**
|
||||
* show debug information in console
|
||||
* @param msg
|
||||
* @param element
|
||||
*/
|
||||
let debugWatchKey = (msg, element) => {
|
||||
if(debug){
|
||||
console.info(msg, element);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get all active (hold down) keys at this moment
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getActiveKeys = () => {
|
||||
return Object.keys(map);
|
||||
};
|
||||
|
||||
/**
|
||||
* callback function that compares two arrays
|
||||
* @param element
|
||||
* @param index
|
||||
* @param array
|
||||
*/
|
||||
let compareKeyLists = function(element, index, array){
|
||||
return this.find(x => x === element);
|
||||
};
|
||||
|
||||
/**
|
||||
* get event names that COULD lead to a "full" event (not all keys pressed yet)
|
||||
* @param keyList
|
||||
* @returns {Array}
|
||||
*/
|
||||
let checkEventNames = (keyList) => {
|
||||
let incompleteEvents = [];
|
||||
for(let event in allEvents){
|
||||
// check if "some" or "all" keys are pressed for en event
|
||||
if( keyList.every(compareKeyLists, allEvents[event].keyNames) ){
|
||||
incompleteEvents.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
return incompleteEvents;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all event names
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getAllEventNames = () => {
|
||||
let eventNames = [];
|
||||
for(let event in allEvents){
|
||||
eventNames.push(event);
|
||||
}
|
||||
return eventNames;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all event names that matches a given keyList
|
||||
* @param keyList
|
||||
* @param checkEvents
|
||||
* @returns {Array}
|
||||
*/
|
||||
let getMatchingEventNames = (keyList, checkEvents) => {
|
||||
checkEvents = checkEvents || getAllEventNames();
|
||||
let events = [];
|
||||
|
||||
for(let event of checkEvents){
|
||||
// check if both key arrays are equal
|
||||
if(
|
||||
allEvents[event].keyNames.every(compareKeyLists, keyList) &&
|
||||
keyList.every(compareKeyLists, allEvents[event].keyNames)
|
||||
){
|
||||
events.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
};
|
||||
|
||||
/**
|
||||
* init global keyWatch interval and check for event trigger (hotKey combinations)
|
||||
*/
|
||||
let init = () => {
|
||||
if( !isInit ){
|
||||
// key watch loop -------------------------------------------------------------------------------
|
||||
let prevActiveKeys = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
* @returns {number} 0: no keys hold, 1: invalid match, 2: partial match, 3: match, 4: alias match, 5: event(s) fired
|
||||
*/
|
||||
let checkForEvents = (e) => {
|
||||
let status = 0;
|
||||
|
||||
// get all pressed keys
|
||||
let activeKeys = getActiveKeys();
|
||||
debugWatchKey('activeKeys', activeKeys);
|
||||
|
||||
// check if "active" keys has changes since last loop
|
||||
if(activeKeys.length){
|
||||
// check for "incomplete" events (not all keys pressed yet)
|
||||
let incompleteEvents = checkEventNames(activeKeys);
|
||||
if(incompleteEvents.length){
|
||||
// "some" event keys pressed OR "all" keys pressed
|
||||
status = 2;
|
||||
|
||||
// check if key combo matches a registered (valid) event
|
||||
let events = getMatchingEventNames(activeKeys, incompleteEvents);
|
||||
if(events.length){
|
||||
status = 3;
|
||||
// check events if there are attached elements to it
|
||||
events.forEach((event) => {
|
||||
// skip events that has an alias and should not be triggered by key combo
|
||||
if( !allEvents[event].alias ){
|
||||
if(allEvents[event].elements){
|
||||
// search for callback functions attached to each element
|
||||
allEvents[event].elements.forEach((domElement) => {
|
||||
let domElementObj = $(domElement);
|
||||
// check if event on this element requires active "focus"
|
||||
let optFocus = domElementObj.data(dataKeyFocusPrefix + event);
|
||||
|
||||
if( !(
|
||||
optFocus &&
|
||||
document.activeElement !== domElement
|
||||
)
|
||||
){
|
||||
// execute callback if valid
|
||||
let callback = domElementObj.data(dataKeyCallbackPrefix + event);
|
||||
if(typeof callback === 'function'){
|
||||
status = 5;
|
||||
callback.call(domElement, domElement, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
status = 4;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}else{
|
||||
// invalid combo
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// store current keys for next loop check
|
||||
prevActiveKeys = activeKeys;
|
||||
|
||||
return status;
|
||||
};
|
||||
|
||||
// set key-events -------------------------------------------------------------------------------
|
||||
let evKeyDown = (e) => {
|
||||
// exclude some HTML Tags from watcher
|
||||
if(
|
||||
e.target.tagName !== 'INPUT' &&
|
||||
e.target.tagName !== 'TEXTAREA' &&
|
||||
!e.target.classList.contains('note-editable') // Summerstyle editor
|
||||
){
|
||||
let key = e.key.toUpperCase();
|
||||
map[key] = true;
|
||||
|
||||
// check for any shortcut combo that triggers an event
|
||||
let status = checkForEvents(e);
|
||||
|
||||
if(
|
||||
status === 2 ||
|
||||
status === 3 ||
|
||||
status === 5
|
||||
){
|
||||
// prevent SOME browser default actions -> we want 'Pathfinder' shortcuts :)
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let evKeyUp = (e) => {
|
||||
if(e.key){
|
||||
let key = e.key.toUpperCase();
|
||||
|
||||
if(map.hasOwnProperty(key)){
|
||||
delete map[key];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let container = $('body');
|
||||
container.on('keydown', evKeyDown);
|
||||
container.on('keyup', evKeyUp);
|
||||
|
||||
// global dom remove listener -------------------------------------------------------------------
|
||||
// -> check whether the removed element had an event listener active and removes them.
|
||||
new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if(mutation.type === 'childList'){
|
||||
for(let i = 0; i < mutation.removedNodes.length; i++){
|
||||
let removedNode = mutation.removedNodes[i];
|
||||
if(typeof removedNode.getAttribute === 'function'){
|
||||
let eventNames = removedNode.getAttribute(dataKeyEvents);
|
||||
if(eventNames){
|
||||
let events = eventNames.split(',');
|
||||
for(let j = 0; i < events.length; j++){
|
||||
let event = events[j];
|
||||
let index = allEvents[event].elements.indexOf(removedNode);
|
||||
if(index > -1){
|
||||
// remove element from event list
|
||||
allEvents[event].elements.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}).observe(document.body, { childList: true, subtree: true });
|
||||
|
||||
isInit = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add a new "shortCut" combination (event) to a DOM element
|
||||
* @param event
|
||||
* @param callback
|
||||
* @param options
|
||||
*/
|
||||
$.fn.watchKey = function(event, callback, options){
|
||||
|
||||
// default options for keyWatcher on elements
|
||||
let defaultOptions = {
|
||||
focus: false, // element must be focused (active)
|
||||
bubbling: true // elements deeper (children) in the DOM can bubble the event up
|
||||
};
|
||||
|
||||
let customOptions = $.extend(true, {}, defaultOptions, options );
|
||||
|
||||
return this.each((i, domElement) => {
|
||||
let element = $(domElement);
|
||||
|
||||
// init global key events
|
||||
init();
|
||||
|
||||
// check if event is "valid" (exists) and is not already set for this element
|
||||
let validEvent = false;
|
||||
if(allEvents[event].elements){
|
||||
if(allEvents[event].elements.indexOf(domElement) === -1){
|
||||
validEvent = true;
|
||||
}else{
|
||||
console.warn('Event "' + event + '" already set');
|
||||
}
|
||||
}else{
|
||||
validEvent = true;
|
||||
allEvents[event].elements = [];
|
||||
}
|
||||
|
||||
if(validEvent){
|
||||
// store callback options to dom element
|
||||
if(customOptions.focus){
|
||||
let dataAttr = dataKeyFocusPrefix + event;
|
||||
element.data(dataAttr, true);
|
||||
|
||||
// check if DOM element has "tabindex" attr -> required to manually set focus() to it
|
||||
if(!domElement.hasAttribute('tabindex')){
|
||||
domElement.setAttribute('tabindex', 0);
|
||||
}
|
||||
|
||||
// element requires a "focus" listener
|
||||
element.off('click.focusKeyWatcher').on('click.focusKeyWatcher', function(e){
|
||||
if(
|
||||
e.target === this ||
|
||||
customOptions.bubbling
|
||||
){
|
||||
this.focus();
|
||||
debugWatchKey('focus set:', this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// check if is key combo has a native JS event that should be used instead
|
||||
if(allEvents[event].alias){
|
||||
element.on(allEvents[event].alias, callback);
|
||||
}else{
|
||||
// store callback function to dom element
|
||||
let dataAttr = dataKeyCallbackPrefix + event;
|
||||
element.data(dataAttr, callback);
|
||||
}
|
||||
|
||||
// add eventName to dom element as attribute ----------------------------------------------------
|
||||
let currentEventNames = element.attr(dataKeyEvents) ? element.attr(dataKeyEvents).split(',') : [];
|
||||
currentEventNames.push(event);
|
||||
element.attr(dataKeyEvents, currentEventNames.join(','));
|
||||
|
||||
// store domElement to event (global)
|
||||
allEvents[event].elements.push(domElement);
|
||||
|
||||
debugWatchKey('new event "' + event + '" registered', domElement);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get a array with all available shortcut groups and their events
|
||||
* @returns {any[]}
|
||||
*/
|
||||
let getGroupedShortcuts = () => {
|
||||
let result = $.extend(true, {}, groups);
|
||||
|
||||
// add combos and events to groups
|
||||
let allEntries = [allCombo, allEvents];
|
||||
|
||||
for(let entries of allEntries){
|
||||
for(let [event, data] of Object.entries(entries)){
|
||||
//format keyNames for UI
|
||||
let keyNames = data.keyNames.map(key => {
|
||||
if(key === 'CONTROL'){
|
||||
key = 'ctrl';
|
||||
}
|
||||
return key;
|
||||
});
|
||||
|
||||
let newEventData = {
|
||||
label: data.label,
|
||||
keyNames: keyNames,
|
||||
list: data.list
|
||||
};
|
||||
|
||||
if( result[data.group].events ){
|
||||
result[data.group].events.push(newEventData);
|
||||
}else{
|
||||
result[data.group].events = [newEventData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert obj into array
|
||||
result = Object.values(result);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return {
|
||||
getGroupedShortcuts: getGroupedShortcuts
|
||||
};
|
||||
});
|
||||
526
public/js/v1.5.2/app/logging.js
Normal file
526
public/js/v1.5.2/app/logging.js
Normal file
@@ -0,0 +1,526 @@
|
||||
/**
|
||||
* logging
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox'
|
||||
], function($, Init, Util, bootbox){
|
||||
|
||||
'use strict';
|
||||
|
||||
let logData = []; // cache object for all log entries
|
||||
let logDataTable = null; // "Datatables" Object
|
||||
|
||||
// Morris charts data
|
||||
let maxGraphDataCount = 30; // max date entries for a graph
|
||||
let chartData = {}; // chart Data object for all Morris Log graphs
|
||||
|
||||
let config = {
|
||||
taskDialogId: 'pf-task-dialog', // id for map "task manager" dialog
|
||||
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
|
||||
moduleHeadlineIconClass: 'pf-module-icon-button' // class for toolbar icons in the head
|
||||
};
|
||||
|
||||
/**
|
||||
* get log time string
|
||||
* @returns {string}
|
||||
*/
|
||||
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
|
||||
*/
|
||||
let showDialog = function(){
|
||||
// dialog content
|
||||
|
||||
requirejs(['text!templates/dialog/task_manager.html', 'mustache', 'datatables.loader'], function(templateTaskManagerDialog, Mustache){
|
||||
let data = {
|
||||
id: config.taskDialogId,
|
||||
dialogDynamicAreaClass: Util.config.dynamicAreaClass,
|
||||
taskDialogStatusAreaClass: config.taskDialogStatusAreaClass,
|
||||
taskDialogLogTableAreaClass: config.taskDialogLogTableAreaClass
|
||||
};
|
||||
|
||||
let contentTaskManager = $( Mustache.render(templateTaskManagerDialog, data) );
|
||||
|
||||
let rowElementGraphs = contentTaskManager.find('.row');
|
||||
let taskDialogLogTableAreaElement = contentTaskManager.find('.' + config.taskDialogLogTableAreaClass);
|
||||
|
||||
let logTable = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
|
||||
});
|
||||
|
||||
taskDialogLogTableAreaElement.append(logTable);
|
||||
|
||||
// init log table
|
||||
logDataTable = logTable.DataTable({
|
||||
dom: '<"row"<"col-xs-3"l><"col-xs-5"B><"col-xs-4"fS>>' +
|
||||
'<"row"<"col-xs-12"tr>>' +
|
||||
'<"row"<"col-xs-5"i><"col-xs-7"p>>',
|
||||
buttons: {
|
||||
name: 'tableTools',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'copy',
|
||||
className: config.moduleHeadlineIconClass,
|
||||
text: '<i class="fas fa-fw fa-copy"></i> copy'
|
||||
},
|
||||
{
|
||||
extend: 'csv',
|
||||
className: config.moduleHeadlineIconClass,
|
||||
text: '<i class="fas fa-fw fa-download"></i> csv'
|
||||
}
|
||||
]
|
||||
},
|
||||
paging: true,
|
||||
ordering: true,
|
||||
order: [ 1, 'desc' ],
|
||||
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_',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
title: '<i class="fas fa-tag"></i>',
|
||||
width: '18px',
|
||||
searchable: false,
|
||||
class: ['text-center'].join(' '),
|
||||
data: 'status'
|
||||
},{
|
||||
targets: 1,
|
||||
title: '<i class="far fa-fw fa-clock"></i> ',
|
||||
width: '50px',
|
||||
searchable: true,
|
||||
class: 'text-right',
|
||||
data: 'time'
|
||||
},{
|
||||
targets: 2,
|
||||
title: '<i class="fas fa-fw fa-history"></i> ',
|
||||
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 ',
|
||||
width: '80px',
|
||||
searchable: false,
|
||||
class: 'text-right',
|
||||
data: 'key'
|
||||
}
|
||||
]
|
||||
|
||||
});
|
||||
|
||||
// open dialog
|
||||
let logDialog = bootbox.dialog({
|
||||
title: 'Task-Manager',
|
||||
message: contentTaskManager,
|
||||
size: 'large',
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'close',
|
||||
className: 'btn-default'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal dialog is shown
|
||||
logDialog.on('shown.bs.modal', function(e){
|
||||
updateSyncStatus();
|
||||
|
||||
// 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: Util.config.dynamicAreaClass
|
||||
}).append( graphElement );
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* updates the log graph for a log key
|
||||
* @param key
|
||||
* @param duration (if undefined -> just update graph with current data)
|
||||
*/
|
||||
let updateLogGraph = function(key, duration){
|
||||
|
||||
// check if graph data already exist
|
||||
if( !(chartData.hasOwnProperty(key))){
|
||||
chartData[key] = {};
|
||||
chartData[key].data = [];
|
||||
chartData[key].graph = null;
|
||||
chartData[key].averageElement = null;
|
||||
chartData[key].updateElement = null;
|
||||
}
|
||||
|
||||
// add new value
|
||||
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){
|
||||
let tempChartData = {
|
||||
data: [],
|
||||
dataSum: 0,
|
||||
average: 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) );
|
||||
}
|
||||
|
||||
tempChartData.data.push({
|
||||
x: x,
|
||||
y: value
|
||||
});
|
||||
}
|
||||
|
||||
// calculate average
|
||||
tempChartData.average = Number( ( tempChartData.dataSum / data.length ).toFixed(2) );
|
||||
|
||||
return tempChartData;
|
||||
}
|
||||
|
||||
let tempChartData = getGraphData(chartData[key].data);
|
||||
|
||||
// add new data to graph (Morris chart) - if is already initialized
|
||||
if(chartData[key].graph !== null){
|
||||
let avgElement = chartData[key].averageElement;
|
||||
let updateElement = chartData[key].updateElement;
|
||||
|
||||
let delay = Util.getCurrentTriggerDelay( key, 0 );
|
||||
|
||||
if(delay){
|
||||
updateElement[0].textContent = ' delay: ' + delay + 'ms ';
|
||||
}
|
||||
|
||||
// set/change average line
|
||||
chartData[key].graph.options.goals = [tempChartData.average];
|
||||
|
||||
// change avg. display
|
||||
avgElement[0].textContent = 'Avg. ' + tempChartData.average + 'ms';
|
||||
|
||||
let avgStatus = getLogStatusByDuration(key, tempChartData.average);
|
||||
let avgStatusClass = Util.getLogInfo( avgStatus, 'class');
|
||||
|
||||
//change avg. display class
|
||||
if( !avgElement.hasClass(avgStatusClass) ){
|
||||
// avg status changed!
|
||||
avgElement.removeClass().addClass('pull-right txt-color ' + avgStatusClass);
|
||||
|
||||
// change goals line color
|
||||
if(avgStatus === 'warning'){
|
||||
chartData[key].graph.options.goalLineColors = ['#e28a0d'];
|
||||
$(document).setProgramStatus('slow connection');
|
||||
}else{
|
||||
chartData[key].graph.options.goalLineColors = ['#5cb85c'];
|
||||
}
|
||||
}
|
||||
|
||||
// set new data and redraw
|
||||
chartData[key].graph.setData( tempChartData.data );
|
||||
}
|
||||
|
||||
return tempChartData.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the log "status" by log duration (ms).
|
||||
* If duration > warning limit -> show as warning
|
||||
* @param logKey
|
||||
* @param logDuration
|
||||
* @returns {string}
|
||||
*/
|
||||
let getLogStatusByDuration = function(logKey, logDuration){
|
||||
let logStatus = 'info';
|
||||
if( logDuration > Init.timer[logKey].EXECUTION_LIMIT ){
|
||||
logStatus = 'warning';
|
||||
}
|
||||
return logStatus;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the css class for a specific log type
|
||||
* @param logType
|
||||
* @returns {string}
|
||||
*/
|
||||
let getLogTypeIconClass = function(logType){
|
||||
|
||||
let logIconClass = '';
|
||||
|
||||
switch(logType){
|
||||
case 'client':
|
||||
logIconClass = 'fa-user';
|
||||
break;
|
||||
case 'server':
|
||||
logIconClass = 'fa-download';
|
||||
break;
|
||||
}
|
||||
|
||||
return logIconClass;
|
||||
};
|
||||
|
||||
/**
|
||||
* init logging -> set global log events
|
||||
*/
|
||||
let init = function(){
|
||||
|
||||
let maxEntries = 150;
|
||||
|
||||
$(window).on('pf:syncStatus', function(){
|
||||
updateSyncStatus();
|
||||
});
|
||||
|
||||
// set global logging listener
|
||||
$(window).on('pf:log', function(e, logKey, options){
|
||||
|
||||
// check required logging information
|
||||
if(
|
||||
options &&
|
||||
options.duration &&
|
||||
options.description
|
||||
){
|
||||
let logDescription = options.description;
|
||||
let logDuration = options.duration;
|
||||
let logType = options.type;
|
||||
|
||||
// check log status by duration
|
||||
let logStatus = getLogStatusByDuration(logKey, logDuration);
|
||||
let statusClass = Util.getLogInfo( logStatus, 'class');
|
||||
let typeIconClass = getLogTypeIconClass(logType);
|
||||
|
||||
// update graph data
|
||||
updateLogGraph(logKey, logDuration);
|
||||
|
||||
let logRowData = {
|
||||
status: '<i class="fas fa-fw fa-circle txt-color ' + statusClass + '"></i>',
|
||||
time: getLogTime(),
|
||||
duration: '<span class="txt-color ' + statusClass + '">' + logDuration + '<small>ms</small></span>',
|
||||
description: logDescription,
|
||||
type: '<i class="fas ' + typeIconClass + '"></i>',
|
||||
key: logKey
|
||||
};
|
||||
|
||||
|
||||
if(logDataTable){
|
||||
// add row if dataTable is initialized before new log
|
||||
logDataTable.row.add( logRowData ).draw(false);
|
||||
}else{
|
||||
// add row data to cache
|
||||
logData.push(logRowData);
|
||||
}
|
||||
}
|
||||
|
||||
// delete old log entries from table ---------------------------------
|
||||
let rowCount = logData.length;
|
||||
|
||||
if( rowCount >= maxEntries ){
|
||||
|
||||
if(logDataTable){
|
||||
logDataTable.rows(0, {order:'index'}).remove().draw(false);
|
||||
}else{
|
||||
logData.shift();
|
||||
}
|
||||
}
|
||||
|
||||
// cache logs in order to keep previous logs in table after reopening the dialog
|
||||
if(logDataTable){
|
||||
logData = logDataTable.rows({order:'index'}).data();
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
getLogTime: getLogTime,
|
||||
showDialog: showDialog
|
||||
};
|
||||
});
|
||||
835
public/js/v1.5.2/app/login.js
Normal file
835
public/js/v1.5.2/app/login.js
Normal file
@@ -0,0 +1,835 @@
|
||||
/**
|
||||
* Main loginPage application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'blueImpGallery',
|
||||
'bootbox',
|
||||
'lazyload',
|
||||
'app/ui/header',
|
||||
'app/ui/logo',
|
||||
'app/ui/demo_map',
|
||||
'dialog/account_settings',
|
||||
'dialog/notification',
|
||||
'dialog/manual',
|
||||
'dialog/changelog',
|
||||
'dialog/credit',
|
||||
'dialog/api_status',
|
||||
], ($, Init, Util, Render, Gallery, bootbox) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
|
||||
// header
|
||||
headerId: 'pf-landing-top', // id for header
|
||||
headerContainerId: 'pf-header-container', // id for header container
|
||||
logoContainerId: 'pf-logo-container', // id for main header logo container
|
||||
headHeaderMapId: 'pf-header-map', // id for header image (svg animation)
|
||||
|
||||
// map bg
|
||||
headMapBgId: 'pf-header-map-bg', // id for header background container
|
||||
mapNeocomId: 'pf-map-neocom', // id for map "neocom" image
|
||||
mapBrowserId: 'pf-map-browser', // id for "browser" image
|
||||
mapBgImageId: 'pf-map-bg-image', // id for "background" map image
|
||||
|
||||
// navigation
|
||||
navigationElementId: 'pf-navbar', // id for navbar element
|
||||
navigationLinkManualClass: 'pf-navbar-manual', // class for "manual" trigger link
|
||||
navigationLinkLicenseClass: 'pf-navbar-license', // class for "license" trigger link
|
||||
navigationVersionLinkClass: 'pf-navbar-version-info', // class for "version information"
|
||||
|
||||
// cookie hint
|
||||
cookieHintId: 'pf-cookie-hint', // id for "cookie hint" element
|
||||
|
||||
// login
|
||||
ssoButtonClass: 'pf-sso-login-button', // class for SSO login button
|
||||
|
||||
// character select
|
||||
characterSelectionClass: 'pf-character-selection', // class for character panel wrapper
|
||||
characterRowAnimateClass: 'pf-character-row-animate', // class for character panel row during animation
|
||||
characterImageWrapperClass: 'pf-character-image-wrapper', // class for image wrapper (animated)
|
||||
characterImageInfoClass: 'pf-character-info', // class for character info layer (visible on hover)
|
||||
dynamicMessageContainerClass: 'pf-dynamic-message-container', // class for "dynamic" (JS) message container
|
||||
|
||||
// gallery
|
||||
galleryId: 'pf-gallery', // id for gallery container
|
||||
galleryThumbImageClass: 'pf-landing-image-preview', // class for gallery thumb images
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container', // id for gallery thumb images
|
||||
galleryCarouselId: 'pf-landing-gallery-carousel', // id for "carousel" element
|
||||
|
||||
// notification panel
|
||||
notificationPanelId: 'pf-notification-panel', // id for "notification panel" (e.g. last update information)
|
||||
|
||||
// sticky panel
|
||||
stickyPanelClass: 'pf-landing-sticky-panel', // class for sticky panels
|
||||
stickyPanelServerId: 'pf-landing-server-panel', // id for EVE Online server status panel
|
||||
stickyPanelAdminId: 'pf-landing-admin-panel', // id for admin login panel
|
||||
|
||||
apiStatusTriggerClass: 'pf-api-status-trigger', // class for "api status" dialog trigger elements
|
||||
|
||||
// animation
|
||||
animateElementClass: 'pf-animate-on-visible', // class for elements that will be animated to show
|
||||
|
||||
defaultAcceptCookieExpire: 365 // default expire for "accept coolies" cookie
|
||||
};
|
||||
|
||||
/**
|
||||
* set link observer for "version info" dialog
|
||||
*/
|
||||
let setVersionLinkObserver = () => {
|
||||
$('.' + config.navigationVersionLinkClass).off('click').on('click', function(e){
|
||||
$.fn.changelogsDialog();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* move panel out of "cookie" accept hint
|
||||
* @param direction
|
||||
*/
|
||||
let moveAdminPanel = (direction) => {
|
||||
let adminPanel = $('#' + config.stickyPanelAdminId);
|
||||
adminPanel.css({bottom: ((direction === 'up') ? '+' : '-') + '=35px'});
|
||||
};
|
||||
|
||||
let setAcceptCookie = () => {
|
||||
Util.setCookie('cookie', 1, config.defaultAcceptCookieExpire, 'd');
|
||||
};
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
let setPageObserver = () => {
|
||||
let ssoButtonElement = $('.' + config.ssoButtonClass);
|
||||
let cookieHintElement = $('#' + config.cookieHintId);
|
||||
|
||||
$(document).on('click', '.' + config.characterSelectionClass + ' a', function(){
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay();
|
||||
});
|
||||
|
||||
$(document).on('click', '.' + config.ssoButtonClass , function(){
|
||||
if(Util.getCookie('cookie') === '1'){
|
||||
// ... cookies accepted no "confirm" shown
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
// cookie hint --------------------------------------------------------
|
||||
cookieHintElement.find('.btn-success').on('click', function(){
|
||||
setAcceptCookie();
|
||||
// confirmation no longer needed on SSO login button
|
||||
ssoButtonElement.confirmation('destroy');
|
||||
});
|
||||
|
||||
cookieHintElement.on('show.bs.collapse', function(){
|
||||
// move admin panel upwards (prevents overlapping with cookie notice)
|
||||
moveAdminPanel('up');
|
||||
});
|
||||
|
||||
cookieHintElement.on('hidden.bs.collapse', function(){
|
||||
moveAdminPanel('down');
|
||||
});
|
||||
|
||||
if(Util.getCookie('cookie') !== '1'){
|
||||
// hint not excepted
|
||||
cookieHintElement.collapse('show');
|
||||
|
||||
// show Cookie accept hint on SSO login button
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'bottom',
|
||||
btnOkClass: 'btn btn-sm btn-default',
|
||||
btnOkLabel: 'dismiss',
|
||||
btnOkIcon: 'fas fa-fw fa-sign-in-alt',
|
||||
title: 'Accept cookies',
|
||||
btnCancelClass: 'btn btn-sm btn-success',
|
||||
btnCancelLabel: 'accept',
|
||||
btnCancelIcon: 'fas fa-fw fa-check',
|
||||
onCancel: function(e, target){
|
||||
// "Accept cookies"
|
||||
setAcceptCookie();
|
||||
|
||||
// set "default" href
|
||||
let href = $(target).data('bs.confirmation').getHref();
|
||||
$(e.target).attr('href', href);
|
||||
},
|
||||
onConfirm : function(e, target){
|
||||
// "NO cookies" => trigger "default" href link action
|
||||
},
|
||||
href: function(target){
|
||||
return $(target).attr('href');
|
||||
}
|
||||
};
|
||||
|
||||
ssoButtonElement.confirmation(confirmationSettings);
|
||||
}
|
||||
|
||||
// manual -------------------------------------------------------------
|
||||
$('.' + config.navigationLinkManualClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
$.fn.showMapManual();
|
||||
});
|
||||
|
||||
// license ------------------------------------------------------------
|
||||
$('.' + config.navigationLinkLicenseClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
$.fn.showCreditsDialog(false, true);
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------------
|
||||
setVersionLinkObserver();
|
||||
|
||||
// tooltips -----------------------------------------------------------
|
||||
let mapTooltipOptions = {
|
||||
toggle: 'tooltip',
|
||||
delay: 150
|
||||
};
|
||||
|
||||
let tooltipElements = $('[title]').not('.slide img');
|
||||
tooltipElements.tooltip(mapTooltipOptions);
|
||||
|
||||
// initial show some tooltips
|
||||
tooltipElements.filter('[data-show="1"]').tooltip('show');
|
||||
};
|
||||
|
||||
/**
|
||||
* init image carousel
|
||||
*/
|
||||
let initCarousel = () => {
|
||||
|
||||
// check if carousel exists
|
||||
if($('#' + config.galleryCarouselId).length === 0){
|
||||
return;
|
||||
}
|
||||
|
||||
// extent "blueimp" gallery for a textFactory method to show HTML templates
|
||||
Gallery.prototype.textFactory = function(obj, callback){
|
||||
let newSlideContent = $('<div>')
|
||||
.addClass('text-content')
|
||||
.attr('imgTitle', obj.title);
|
||||
|
||||
// render HTML file (template)
|
||||
let moduleData = {
|
||||
id: config.headHeaderMapId,
|
||||
bgId: config.headMapBgId,
|
||||
neocomId: config.mapNeocomId,
|
||||
browserId: config.mapBrowserId,
|
||||
mapBgImageId: config.mapBgImageId
|
||||
};
|
||||
|
||||
Render.render(obj.href, moduleData)
|
||||
.then(payload => newSlideContent.append(payload))
|
||||
.then(payload => callback({type: 'complete', target: payload[0]}));
|
||||
|
||||
return newSlideContent[0];
|
||||
};
|
||||
|
||||
// initialize carousel ------------------------------------------------
|
||||
let carousel = new Gallery([
|
||||
{
|
||||
imgTitle: 'Browser',
|
||||
href: 'ui/map',
|
||||
type: 'text/html'
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/responsive.jpg',
|
||||
imgTitle: 'Responsive layout',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_1.jpg',
|
||||
imgTitle: 'Map view',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_3.jpg',
|
||||
imgTitle: 'Map information',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_2.jpg',
|
||||
imgTitle: 'System information',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
}
|
||||
], {
|
||||
container: '#' + config.galleryCarouselId,
|
||||
carousel: true,
|
||||
startSlideshow: false,
|
||||
titleProperty: 'imgTitle',
|
||||
transitionSpeed: 600,
|
||||
slideshowInterval: 5000,
|
||||
preloadRange: 1,
|
||||
onopened: function(){
|
||||
// Callback function executed when the Gallery has been initialized
|
||||
// and the initialization transition has been completed.
|
||||
// -> show "demo" map
|
||||
|
||||
// set title for first slide
|
||||
$(this.options.container).find(this.options.titleElement).text('Browser view');
|
||||
|
||||
$('#' + config.headHeaderMapId).drawDemoMap(function(){
|
||||
|
||||
// zoom map SVGs
|
||||
$('#' + config.headHeaderMapId + ' svg').velocity({
|
||||
scaleX: 0.66,
|
||||
scaleY: 0.66
|
||||
}, {
|
||||
duration: 360
|
||||
});
|
||||
|
||||
// position map container
|
||||
$('#' + config.headHeaderMapId).velocity({
|
||||
marginTop: '130px',
|
||||
marginLeft: '-50px'
|
||||
}, {
|
||||
duration: 360,
|
||||
complete: function(){
|
||||
// show browser
|
||||
$('#' + config.mapBrowserId).velocity('transition.slideUpBigIn', {
|
||||
duration: 360,
|
||||
complete: function(){
|
||||
// show neocom
|
||||
$('#' + config.mapNeocomId).velocity('transition.slideLeftIn', {
|
||||
duration: 180
|
||||
});
|
||||
|
||||
// show background
|
||||
$('#' + config.mapBgImageId).velocity('transition.shrinkIn', {
|
||||
duration: 360
|
||||
});
|
||||
|
||||
// when map is shown -> start carousel looping
|
||||
carousel.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get all thumbnail elements
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
let getThumbnailElements = () => {
|
||||
return $('a[data-gallery="#' + config.galleryId + '"]').not('.disabled');
|
||||
};
|
||||
|
||||
/**
|
||||
* init gallery for thumbnail elements
|
||||
* @param newElements
|
||||
*/
|
||||
let initGallery = (newElements) => {
|
||||
if( newElements.length > 0){
|
||||
// We have to add ALL thumbnail elements to the gallery!
|
||||
// -> even those which are invisible (not lazyLoaded) now!
|
||||
// -> This is required for "swipe" through all images
|
||||
let allThumbLinks = getThumbnailElements();
|
||||
|
||||
requirejs(['blueImpGalleryBootstrap'], () => {
|
||||
$(newElements).each(function(){
|
||||
let borderless = false;
|
||||
|
||||
let galleryElement = $('#' + config.galleryId);
|
||||
galleryElement.data('useBootstrapModal', !borderless);
|
||||
galleryElement.toggleClass('blueimp-gallery-controls', borderless);
|
||||
|
||||
$(this).on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
e = e || window.event;
|
||||
let target = e.target || e.srcElement;
|
||||
let link = target.src ? target.parentNode : target;
|
||||
|
||||
let options = {
|
||||
index: link,
|
||||
event: e,
|
||||
container: '#' + config.galleryId,
|
||||
titleProperty: 'description'
|
||||
};
|
||||
|
||||
new Gallery(allThumbLinks, options);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init "YouTube" video preview
|
||||
*/
|
||||
let initYoutube = () => {
|
||||
|
||||
$('.youtube').each(function(){
|
||||
// Based on the YouTube ID, we can easily find the thumbnail image
|
||||
$(this).css('background-image', 'url(//i.ytimg.com/vi/' + this.id + '/sddefault.jpg)');
|
||||
|
||||
// Overlay the Play icon to make it look like a video player
|
||||
$(this).append($('<div/>', {'class': 'play'}));
|
||||
|
||||
$(document).delegate('#' + this.id, 'click', function(){
|
||||
// Create an iFrame with autoplay set to true
|
||||
let iFrameUrl = '//www.youtube.com/embed/' + this.id + '?autoplay=1&autohide=1';
|
||||
if( $(this).data('params') ){
|
||||
iFrameUrl += '&'+$(this).data('params');
|
||||
}
|
||||
|
||||
// The height and width of the iFrame should be the same as parent
|
||||
let iFrame = $('<iframe/>', {
|
||||
frameborder: '0',
|
||||
src: iFrameUrl,
|
||||
width: $(this).width(),
|
||||
height: $(this).height(),
|
||||
class: 'pricing-big'
|
||||
});
|
||||
|
||||
// Replace the YouTube thumbnail with YouTube HTML5 Player
|
||||
$(this).replaceWith(iFrame);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init scrollSpy for navigation bar
|
||||
*/
|
||||
let initScrollSpy = () => {
|
||||
// init scrollspy
|
||||
|
||||
// show elements that are currently in the viewport
|
||||
let showVisibleElements = () => {
|
||||
// find all elements that should be animated
|
||||
let visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
$(visibleElements).removeClass( config.animateElementClass );
|
||||
|
||||
$(visibleElements).velocity('transition.flipXIn', {
|
||||
duration: 600,
|
||||
stagger: 60,
|
||||
delay: 500,
|
||||
complete: function(element){
|
||||
// show "fade" modules (e.g. ribbons)
|
||||
$(element).find('.fade').addClass('in');
|
||||
|
||||
// init gallery for "now" visible elements
|
||||
let newGalleryElements = $(element).filter('[data-gallery="#' + config.galleryId + '"]');
|
||||
initGallery(newGalleryElements);
|
||||
},
|
||||
visibility: 'visible'
|
||||
});
|
||||
};
|
||||
|
||||
$( window ).scroll(() => {
|
||||
// check for new visible elements
|
||||
showVisibleElements();
|
||||
});
|
||||
|
||||
// initial check for visible elements
|
||||
showVisibleElements();
|
||||
|
||||
// event listener for navigation links
|
||||
Util.initPageScroll('#' + config.navigationElementId);
|
||||
};
|
||||
|
||||
/**
|
||||
* get current EVE-Online server status
|
||||
* -> show "server panel"
|
||||
*/
|
||||
let initServerStatus = () => {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getServerStatus,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData, textStatus, request){
|
||||
|
||||
let data = {
|
||||
stickyPanelServerId: config.stickyPanelServerId,
|
||||
stickyPanelClass: config.stickyPanelClass,
|
||||
apiStatusTriggerClass: config.apiStatusTriggerClass,
|
||||
server: responseData.server,
|
||||
api: responseData.api,
|
||||
statusFormat: () => {
|
||||
return (val, render) => {
|
||||
switch(render(val)){
|
||||
case 'online':
|
||||
case 'green': return 'txt-color-green';
|
||||
case 'vip':
|
||||
case 'yellow': return 'txt-color-orange';
|
||||
case 'offline':
|
||||
case 'red': return 'txt-color-red';
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
requirejs(['text!templates/ui/server_panel.html', 'mustache'], function(template, Mustache){
|
||||
let content = Mustache.render(template, data);
|
||||
$('#' + config.headerId).prepend(content);
|
||||
let stickyPanelServer = $('#' + config.stickyPanelServerId);
|
||||
stickyPanelServer.velocity('transition.slideLeftBigIn', {
|
||||
duration: 240
|
||||
});
|
||||
|
||||
// set observer for api status dialog
|
||||
stickyPanelServer.on('click', '.' + config.apiStatusTriggerClass, function(){
|
||||
$.fn.apiStatusDialog(data.api);
|
||||
});
|
||||
});
|
||||
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* show "notification panel" to user
|
||||
* -> checks if panel not already shown
|
||||
*/
|
||||
let initNotificationPanel = () => {
|
||||
let storageKey = 'notification_panel';
|
||||
let currentVersion = Util.getVersion();
|
||||
|
||||
let showNotificationPanel = () => {
|
||||
let data = {
|
||||
version: Util.getVersion()
|
||||
};
|
||||
|
||||
requirejs(['text!templates/ui/notice.html', 'mustache'], (template, Mustache) => {
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let notificationPanel = $('#' + config.notificationPanelId);
|
||||
notificationPanel.html(content);
|
||||
notificationPanel.velocity('transition.slideUpIn', {
|
||||
duration: 300,
|
||||
complete: function(){
|
||||
setVersionLinkObserver();
|
||||
|
||||
// mark panel as "shown"
|
||||
Util.getLocalStorage().setItem(storageKey, currentVersion);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data){
|
||||
// check if panel was shown before
|
||||
if(data){
|
||||
if(data !== this.version){
|
||||
// show current panel
|
||||
showNotificationPanel();
|
||||
}
|
||||
}else{
|
||||
// show current panel
|
||||
showNotificationPanel();
|
||||
}
|
||||
}.bind({
|
||||
version: currentVersion
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* load character data from cookie information
|
||||
* -> all validation is done server side!
|
||||
*/
|
||||
let initCharacterSelect = function(){
|
||||
|
||||
/**
|
||||
* init panel animation for an element
|
||||
* @param imageWrapperElement
|
||||
*/
|
||||
let initCharacterAnimation = function(imageWrapperElement){
|
||||
|
||||
imageWrapperElement.velocity('stop').velocity('transition.flipBounceXIn', {
|
||||
display: 'inline-block',
|
||||
drag: true,
|
||||
duration: 500
|
||||
});
|
||||
|
||||
// Hover effect for character info layer
|
||||
imageWrapperElement.hoverIntent(function(e){
|
||||
let characterInfoElement = $(this).find('.' + config.characterImageInfoClass);
|
||||
|
||||
characterInfoElement.velocity('finish').velocity({
|
||||
width: ['100%', [ 400, 15 ] ]
|
||||
},{
|
||||
easing: 'easeOutSine'
|
||||
});
|
||||
}, function(e){
|
||||
let characterInfoElement = $(this).find('.' + config.characterImageInfoClass);
|
||||
|
||||
characterInfoElement.velocity('finish').velocity({
|
||||
width: 0
|
||||
},{
|
||||
duration: 150,
|
||||
easing: 'easeOutSine'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* update all character panels -> set CSS class (e.g. after some panels were added/removed,..)
|
||||
*/
|
||||
let updateCharacterPanels = function(){
|
||||
let characterRows = $('.' + config.characterSelectionClass + ' .' + Util.config.dynamicAreaClass).parent();
|
||||
let rowClassIdentifier = ((12 / characterRows.length ) <= 3) ? 3 : (12 / characterRows.length);
|
||||
$(characterRows).removeClass().addClass('col-sm-' + rowClassIdentifier);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
let removeCharacterPanel = function(panelElement){
|
||||
$(panelElement).velocity('transition.expandOut', {
|
||||
duration: 250,
|
||||
complete: function(){
|
||||
// lock row for CSS animations while removing...
|
||||
$(this).parent().addClass(config.characterRowAnimateClass);
|
||||
|
||||
$(this).parent().velocity({
|
||||
width: 0
|
||||
},{
|
||||
easing: 'ease',
|
||||
duration: 300,
|
||||
complete: function(){
|
||||
$(this).remove();
|
||||
// reset column CSS classes for all existing panels
|
||||
updateCharacterPanels();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
let getCharacterAuthLabel = (authStatus) => {
|
||||
let label = '';
|
||||
switch(authStatus){
|
||||
case 'UNKNOWN':
|
||||
label = 'ERROR';
|
||||
break;
|
||||
case 'CHARACTER':
|
||||
case 'CORPORATION':
|
||||
case 'ALLIANCE':
|
||||
label = 'INVALID';
|
||||
break;
|
||||
default:
|
||||
label = authStatus;
|
||||
break;
|
||||
}
|
||||
return label;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// request character data for each character panel
|
||||
requirejs(['text!templates/ui/character_panel.html', 'mustache'], function(template, Mustache){
|
||||
|
||||
$('.' + config.characterSelectionClass + ' .' + Util.config.dynamicAreaClass).each(function(){
|
||||
let characterElement = $(this);
|
||||
|
||||
characterElement.showLoadingAnimation();
|
||||
|
||||
let requestData = {
|
||||
cookie: characterElement.data('cookie')
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getCookieCharacterData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
cookieName: requestData.cookie,
|
||||
characterElement: characterElement,
|
||||
browserTabId: Util.getBrowserTabId()
|
||||
}
|
||||
}).done(function(responseData, textStatus, request){
|
||||
this.characterElement.hideLoadingAnimation();
|
||||
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
$('.' + config.dynamicMessageContainerClass).showMessage({
|
||||
dismissible: false,
|
||||
type: responseData.error[0].type,
|
||||
title: 'Character verification failed',
|
||||
text: responseData.error[0].message
|
||||
});
|
||||
}
|
||||
|
||||
if(responseData.hasOwnProperty('character')){
|
||||
|
||||
let data = {
|
||||
link: this.characterElement.data('href'),
|
||||
cookieName: this.cookieName,
|
||||
browserTabId: this.browserTabId,
|
||||
character: responseData.character,
|
||||
isManager: Util.getObjVal(responseData, 'character.role.name') === 'CORPORATION',
|
||||
isAdmin: Util.getObjVal(responseData, 'character.role.name') === 'SUPER',
|
||||
authLabel: getCharacterAuthLabel(responseData.character.authStatus),
|
||||
authOK: responseData.character.authStatus === 'OK',
|
||||
hasActiveSession: responseData.character.hasActiveSession === true
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
this.characterElement.html(content);
|
||||
|
||||
// show character panel (animation settings)
|
||||
initCharacterAnimation(this.characterElement.find('.' + config.characterImageWrapperClass));
|
||||
}else{
|
||||
// character data not available -> remove panel
|
||||
removeCharacterPanel(this.characterElement);
|
||||
}
|
||||
}).fail(function(jqXHR, status, error){
|
||||
let characterElement = this.characterElement;
|
||||
characterElement.hideLoadingAnimation();
|
||||
|
||||
// character data not available -> remove panel
|
||||
removeCharacterPanel(this.characterElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* default ajax error handler
|
||||
* -> show user notifications
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
let handleAjaxErrorResponse = (jqXHR, status, error) => {
|
||||
|
||||
let type = status;
|
||||
let title = 'Status ' + jqXHR.status + ': ' + error;
|
||||
let message = '';
|
||||
|
||||
if(jqXHR.responseText){
|
||||
let errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
for(let i = 0; i < errorObj.error.length; i++){
|
||||
let errorData = errorObj.error[i];
|
||||
type = errorData.type;
|
||||
title = 'Status ' + errorData.code + ': ' + errorData.status;
|
||||
message = errorData.message;
|
||||
|
||||
Util.showNotify({title: title, text: message, type: type});
|
||||
}
|
||||
}
|
||||
}else{
|
||||
Util.showNotify({title: title, text: message, type: type});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* main init "landing" page
|
||||
*/
|
||||
$(() => {
|
||||
// clear sessionStorage
|
||||
Util.clearSessionStorage();
|
||||
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
// set Dialog default config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// show log off message
|
||||
let isLogOut = location.search.split('logout')[1];
|
||||
if(isLogOut !== undefined){
|
||||
|
||||
// show logout dialog
|
||||
let options = {
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'close',
|
||||
className: ['btn-default'].join(' ')
|
||||
}
|
||||
},
|
||||
content: {
|
||||
icon: 'fa-sign-out-alt',
|
||||
class: 'txt-color-warning',
|
||||
title: 'Logout',
|
||||
headline: 'Logout',
|
||||
text: [
|
||||
'For security reasons, you were logged out automatically',
|
||||
'Please log in again'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.showNotificationDialog(options);
|
||||
|
||||
// change url (remove logout parameter)
|
||||
if(history.pushState){
|
||||
history.pushState({}, '', location.protocol + '//' + location.host + location.pathname);
|
||||
}
|
||||
}
|
||||
|
||||
// "Lock" default link action (=> open in new tab)!
|
||||
// -> until "gallery" is initialized (=> wait animation complete!)
|
||||
getThumbnailElements().on('click', function(e){
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// init "lazy loading" for images
|
||||
$('.' + config.galleryThumbImageClass).lazyload({
|
||||
threshold : 300
|
||||
});
|
||||
|
||||
// hide splash loading animation
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
// init server status information
|
||||
initServerStatus();
|
||||
|
||||
// init notification panel
|
||||
initNotificationPanel();
|
||||
|
||||
// init character select
|
||||
initCharacterSelect();
|
||||
|
||||
// init page observer
|
||||
setPageObserver();
|
||||
|
||||
// init carousel
|
||||
initCarousel();
|
||||
|
||||
// init scrollSpy
|
||||
// -> after "Carousel"! required for correct "viewport" calculation (Gallery)!
|
||||
initScrollSpy();
|
||||
|
||||
// init youtube videos
|
||||
initYoutube();
|
||||
|
||||
// draw header logo
|
||||
$('#' + config.logoContainerId).drawLogo(() => {
|
||||
// init header animation
|
||||
$('#' + config.headerContainerId).initHeader(() => {
|
||||
|
||||
});
|
||||
}, false);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
299
public/js/v1.5.2/app/map/contextmenu.js
Normal file
299
public/js/v1.5.2/app/map/contextmenu.js
Normal file
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
* context menu
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/render'
|
||||
], ($, Render) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
mapContextMenuId: 'pf-map-contextmenu', // id for "maps" context menu
|
||||
connectionContextMenuId: 'pf-map-connection-contextmenu', // id for "connections" context menu
|
||||
endpointContextMenuId: 'pf-map-endpoint-contextmenu', // id for "endpoints" context menu
|
||||
systemContextMenuId: 'pf-map-system-contextmenu', // id for "systems" context menu
|
||||
|
||||
animationInType: 'transition.flipXIn',
|
||||
animationInDuration: 150,
|
||||
animationOutType: 'transition.flipXOut',
|
||||
animationOutDuration: 150
|
||||
};
|
||||
|
||||
/**
|
||||
* calc menu X coordinate
|
||||
* @param e
|
||||
* @param menuWidth
|
||||
* @returns {number|*}
|
||||
*/
|
||||
let getMenuLeftCoordinate = (e, menuWidth) => {
|
||||
let mouseWidth = e.pageX;
|
||||
let pageWidth = $(window).width();
|
||||
|
||||
// opening menu would pass the side of the page
|
||||
if(mouseWidth + menuWidth > pageWidth &&
|
||||
menuWidth < mouseWidth){
|
||||
return mouseWidth - menuWidth;
|
||||
}
|
||||
return mouseWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* calc menu Y coordinate
|
||||
* @param e
|
||||
* @param menuHeight
|
||||
* @returns {number|*}
|
||||
*/
|
||||
let getMenuTopCoordinate = (e, menuHeight) => {
|
||||
let mouseHeight = e.pageY;
|
||||
let pageHeight = $(window).height();
|
||||
|
||||
// opening menu would pass the bottom of the page
|
||||
if(mouseHeight + menuHeight > pageHeight &&
|
||||
menuHeight < mouseHeight){
|
||||
return mouseHeight - menuHeight;
|
||||
}
|
||||
return mouseHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* render context menu template for maps
|
||||
* @returns {*}
|
||||
*/
|
||||
let renderMapContextMenu = () => {
|
||||
let moduleData = {
|
||||
id: config.mapContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-plus', action: 'add_system', text: 'add system'},
|
||||
{icon: 'fa-object-ungroup', action: 'select_all', text: 'select all'},
|
||||
{icon: 'fa-filter', action: 'filter_scope', text: 'filter scope', subitems: [
|
||||
{subIcon: '', subAction: 'filter_wh', subText: 'wormhole'},
|
||||
{subIcon: '', subAction: 'filter_stargate', subText: 'stargate'},
|
||||
{subIcon: '', subAction: 'filter_jumpbridge', subText: 'jumpbridge'},
|
||||
{subIcon: '', subAction: 'filter_abyssal', subText: 'abyssal'}
|
||||
]},
|
||||
{icon: 'fa-sitemap', action: 'map', text: 'map', subitems: [
|
||||
{subIcon: 'fa-edit', subAction: 'map_edit', subText: 'edit map'},
|
||||
{subIcon: 'fa-street-view', subAction: 'map_info', subText: 'map info'},
|
||||
]},
|
||||
{divider: true, action: 'delete_systems'},
|
||||
{icon: 'fa-trash', action: 'delete_systems', text: 'delete systems'}
|
||||
]
|
||||
};
|
||||
|
||||
return Render.render('modules/contextmenu', moduleData);
|
||||
};
|
||||
|
||||
/**
|
||||
* render context menu template for connections
|
||||
* @returns {*}
|
||||
*/
|
||||
let renderConnectionContextMenu = () => {
|
||||
let moduleData = {
|
||||
id: config.connectionContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-plane', action: 'frigate', text: 'frigate hole'},
|
||||
{icon: 'fa-exclamation-triangle', action: 'preserve_mass', text: 'preserve mass'},
|
||||
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
|
||||
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
|
||||
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
|
||||
|
||||
]},
|
||||
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'change status', subitems: [
|
||||
{subIcon: 'fa-clock', subAction: 'wh_eol', subText: 'toggle EOL'},
|
||||
{subDivider: true},
|
||||
{subIcon: 'fa-circle', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
|
||||
{subIcon: 'fa-adjust', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
|
||||
{subIcon: 'fa-circle', subAction: 'status_critical', subText: 'stage 3 (critical)'}
|
||||
|
||||
]},
|
||||
{divider: true, action: 'separator'} ,
|
||||
{icon: 'fa-unlink', action: 'delete_connection', text: 'detach'}
|
||||
]
|
||||
};
|
||||
|
||||
return Render.render('modules/contextmenu', moduleData);
|
||||
};
|
||||
|
||||
/**
|
||||
* render context menu template for endpoints
|
||||
* @returns {*}
|
||||
*/
|
||||
let renderEndpointContextMenu = () => {
|
||||
let moduleData = {
|
||||
id: config.endpointContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-globe', action: 'bubble', text: 'bubbled'}
|
||||
]
|
||||
};
|
||||
|
||||
return Render.render('modules/contextmenu', moduleData);
|
||||
};
|
||||
|
||||
/**
|
||||
* render context menu template for systems
|
||||
* @param systemStatusData
|
||||
* @returns {*}
|
||||
*/
|
||||
let renderSystemContextMenu = systemStatusData => {
|
||||
let statusData = [];
|
||||
for(let [statusName, data] of Object.entries(systemStatusData)){
|
||||
statusData.push({
|
||||
subIcon: 'fa-tag',
|
||||
subIconClass: data.class,
|
||||
subAction: 'change_status_' + statusName,
|
||||
subText: data.label
|
||||
});
|
||||
}
|
||||
|
||||
let moduleData = {
|
||||
id: config.systemContextMenuId,
|
||||
items: [
|
||||
{icon: 'fa-plus', action: 'add_system', text: 'add system'},
|
||||
{icon: 'fa-lock', action: 'lock_system', text: 'lock system'},
|
||||
{icon: 'fa-volume-up', action: 'set_rally', text: 'set rally point'},
|
||||
{icon: 'fa-tags', text: 'set status', subitems: statusData},
|
||||
{icon: 'fa-route', action: 'find_route', text: 'find route'},
|
||||
{icon: 'fa-object-group', action: 'select_connections', text: 'select connections'},
|
||||
{icon: 'fa-reply fa-rotate-180', text: 'waypoints', subitems: [
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'set_destination', subText: 'set destination'},
|
||||
{subDivider: true, action: ''},
|
||||
{subIcon: 'fa-step-backward', subAction: 'add_first_waypoint', subText: 'add new [start]'},
|
||||
{subIcon: 'fa-step-forward', subAction: 'add_last_waypoint', subText: 'add new [end]'}
|
||||
]},
|
||||
{divider: true, action: 'delete_system'},
|
||||
{icon: 'fa-trash', action: 'delete_system', text: 'delete system(s)'}
|
||||
]
|
||||
};
|
||||
|
||||
return Render.render('modules/contextmenu', moduleData);
|
||||
};
|
||||
|
||||
/**
|
||||
* prepare (hide/activate/disable) some menu options
|
||||
* @param menuElement
|
||||
* @param hiddenOptions
|
||||
* @param activeOptions
|
||||
* @param disabledOptions
|
||||
* @returns {*}
|
||||
*/
|
||||
let prepareMenu = (menuElement, hiddenOptions, activeOptions, disabledOptions) => {
|
||||
let menuLiElements = menuElement.find('li');
|
||||
|
||||
// reset all menu entries
|
||||
menuLiElements.removeClass('active').removeClass('disabled').show();
|
||||
|
||||
// hide specific menu entries
|
||||
for(let action of hiddenOptions){
|
||||
menuElement.find('li[data-action="' + action + '"]').hide();
|
||||
}
|
||||
|
||||
//set active specific menu entries
|
||||
for(let action of activeOptions){
|
||||
menuElement.find('li[data-action="' + action + '"]').addClass('active');
|
||||
}
|
||||
|
||||
//disable specific menu entries
|
||||
for(let action of disabledOptions){
|
||||
menuElement.find('li[data-action="' + action + '"]').addClass('disabled');
|
||||
}
|
||||
|
||||
return menuElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* close all context menus (map, connection,...)
|
||||
* @param excludeMenu
|
||||
*/
|
||||
let closeMenus = excludeMenu => {
|
||||
let allMenus = $('.dropdown-menu[role="menu"]');
|
||||
if(excludeMenu){
|
||||
allMenus = allMenus.not(excludeMenu);
|
||||
}
|
||||
|
||||
allMenus.velocity(config.animationOutType, {
|
||||
duration: config.animationOutDuration
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* open menu handler
|
||||
* @param menuConfig
|
||||
* @param e
|
||||
* @param context
|
||||
*/
|
||||
let openMenu = (menuConfig, e, context) => {
|
||||
let menuElement = $('#' + menuConfig.id);
|
||||
|
||||
// close all other context menus
|
||||
closeMenus(menuElement);
|
||||
|
||||
// remove menu list click event
|
||||
// -> required in case the close handler could not remove them properly
|
||||
// -> this happens if menu re-opens without closing (2x right click)
|
||||
menuElement.off('click.contextMenuSelect', 'li');
|
||||
|
||||
// hide/activate/disable
|
||||
menuElement = prepareMenu(menuElement, menuConfig.hidden, menuConfig.active, menuConfig.disabled);
|
||||
|
||||
menuElement.css({
|
||||
position: 'absolute',
|
||||
left: getMenuLeftCoordinate(e, menuElement.width()),
|
||||
top: getMenuTopCoordinate(e, menuElement.height())
|
||||
}).velocity(config.animationInType, {
|
||||
duration: config.animationInDuration,
|
||||
complete: function(){
|
||||
context = {
|
||||
original: {
|
||||
event: e,
|
||||
context: context,
|
||||
},
|
||||
selectCallback: menuConfig.selectCallback
|
||||
};
|
||||
|
||||
$(this).one('click.contextMenuSelect', 'li', context, selectHandler);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* menu item select handler
|
||||
* @param e
|
||||
*/
|
||||
let selectHandler = e => {
|
||||
if(e.data.selectCallback){
|
||||
e.data.selectCallback(
|
||||
$(e.currentTarget).attr('data-action'),
|
||||
e.data.original.context.component,
|
||||
e.data.original.event
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* default config (skeleton) for valid context menu configuration
|
||||
* @returns {{hidden: Array, active: Array, disabled: Array, id: string, selectCallback: null}}
|
||||
*/
|
||||
let defaultMenuOptionConfig = () => {
|
||||
return {
|
||||
'id': '',
|
||||
'selectCallback': null,
|
||||
'hidden': [],
|
||||
'active': [],
|
||||
'disabled': []
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
defaultMenuOptionConfig: defaultMenuOptionConfig,
|
||||
renderMapContextMenu: renderMapContextMenu,
|
||||
renderConnectionContextMenu: renderConnectionContextMenu,
|
||||
renderEndpointContextMenu: renderEndpointContextMenu,
|
||||
renderSystemContextMenu: renderSystemContextMenu,
|
||||
openMenu: openMenu,
|
||||
closeMenus: closeMenus
|
||||
};
|
||||
});
|
||||
423
public/js/v1.5.2/app/map/layout.js
Normal file
423
public/js/v1.5.2/app/map/layout.js
Normal file
@@ -0,0 +1,423 @@
|
||||
define(() => {
|
||||
'use strict';
|
||||
|
||||
class Position {
|
||||
|
||||
constructor(config){
|
||||
this._defaultConfig = {
|
||||
container: null, // parent DOM container element
|
||||
center: null, // DOM elements that works as center
|
||||
elementClass: 'pf-system', // class for all elements
|
||||
defaultGapX: 50,
|
||||
defaultGapY: 50,
|
||||
gapX: 50, // leave gap between elements (x-axis)
|
||||
gapY: 50, // leave gap between elements (y-axis)
|
||||
loops: 2, // max loops around "center" for search
|
||||
grid: false, // set to [20, 20] to force grid snapping
|
||||
newElementWidth: 100, // width for new element
|
||||
newElementHeight: 22, // height for new element
|
||||
debug: false, // render debug elements
|
||||
debugElementClass: 'pf-system-debug' // class for debug elements
|
||||
};
|
||||
|
||||
this._config = Object.assign({}, this._defaultConfig, config);
|
||||
|
||||
/**
|
||||
* convert degree into radial unit
|
||||
* @param deg
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
this._degToRad = (deg) => {
|
||||
return deg * Math.PI / 180;
|
||||
};
|
||||
|
||||
/**
|
||||
* get element dimension/position of a DOM element
|
||||
* @param element
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._getElementDimension = (element) => {
|
||||
let dim = null;
|
||||
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
let a = 0;
|
||||
let b = 0;
|
||||
let width = this._config.newElementWidth;
|
||||
let height = this._config.newElementHeight;
|
||||
|
||||
if(Array.isArray(element)){
|
||||
// xy coordinates
|
||||
let point = [
|
||||
element[0] ? parseInt(element[0], 10) : 0,
|
||||
element[1] ? parseInt(element[1], 10) : 0
|
||||
];
|
||||
|
||||
if(this._config.grid){
|
||||
point = this._transformPointToGrid(point);
|
||||
}
|
||||
|
||||
left = point[0];
|
||||
top = point[1];
|
||||
a = this._config.gapX;
|
||||
b = this._config.gapY;
|
||||
}else if(element){
|
||||
// DOM element
|
||||
left = element.style.left ? parseInt(element.style.left, 10) : 0;
|
||||
top = element.style.top ? parseInt(element.style.top, 10) : 0;
|
||||
a = parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX;
|
||||
b = parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY;
|
||||
width = element.offsetWidth;
|
||||
height = element.offsetHeight;
|
||||
}
|
||||
|
||||
// add "gap" to a and b in order to have some space around elements
|
||||
return {
|
||||
left: left,
|
||||
top: top,
|
||||
a: a,
|
||||
b: b,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get x/y coordinate on an eclipse around a 2D area by a given radial angle
|
||||
* @param dim
|
||||
* @param angle
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._getEllipseCoordinates = (dim, angle) => {
|
||||
let coordinates = null;
|
||||
if(dim){
|
||||
angle = this._degToRad(angle);
|
||||
coordinates = {
|
||||
x: Math.round((dim.a * dim.b) / Math.sqrt(Math.pow(dim.b, 2) + Math.pow(dim.a, 2) * Math.pow(Math.tan(angle), 2) )),
|
||||
y: Math.round((dim.a * dim.b) / Math.sqrt(Math.pow(dim.a, 2) + Math.pow(dim.b, 2) / Math.pow(Math.tan(angle), 2) ))
|
||||
};
|
||||
|
||||
// invert coordinate based on quadrant ------------------------------------------------------------
|
||||
if( angle > (Math.PI / 2) && angle < (3 * Math.PI / 2) ){
|
||||
coordinates.x = coordinates.x * -1;
|
||||
}
|
||||
|
||||
if( angle > Math.PI && angle < (2 * Math.PI) ){
|
||||
coordinates.y = coordinates.y * -1;
|
||||
}
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
/**
|
||||
* get dimensions of all surrounding elements
|
||||
* @returns {Array}
|
||||
* @private
|
||||
*/
|
||||
this._getAllElementDimensions = () => {
|
||||
let dimensions = [];
|
||||
let surroundingElements = this._getContainer().getElementsByClassName(this._config.elementClass);
|
||||
for(let element of surroundingElements){
|
||||
dimensions.push(this._getElementDimension(element));
|
||||
}
|
||||
return dimensions;
|
||||
};
|
||||
|
||||
/**
|
||||
* transform a x/y point into a x/y point that snaps to grid
|
||||
* @param point
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._transformPointToGrid = (point) => {
|
||||
point[0] = Math.floor(point[0] / this._config.grid[0]) * this._config.grid[0];
|
||||
point[1] = Math.floor(point[1] / this._config.grid[1]) * this._config.grid[1];
|
||||
return point;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform a x/y coordinate into a 2D element with width/height
|
||||
* @param centerDimension
|
||||
* @param coordinate
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._transformCoordinate = (centerDimension, coordinate) => {
|
||||
let dim = null;
|
||||
if(centerDimension && coordinate){
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
|
||||
// calculate left/top based on coordinate system quadrant -----------------------------------------
|
||||
// -> flip horizontal in Q2 and Q3
|
||||
if(coordinate.x >= 0 && coordinate.y > 0){
|
||||
// 1. quadrant
|
||||
left = centerDimension.left + centerDimension.a - this._config.gapX + coordinate.x;
|
||||
top = centerDimension.top + 2 * (centerDimension.b - this._config.gapY) - Math.abs(coordinate.y) - this._config.newElementHeight;
|
||||
}else if(coordinate.x < 0 && coordinate.y > 0){
|
||||
// 2. quadrant
|
||||
left = centerDimension.left + centerDimension.a - this._config.gapX + coordinate.x - this._config.newElementWidth;
|
||||
top = centerDimension.top + 2 * (centerDimension.b - this._config.gapY) - Math.abs(coordinate.y) - this._config.newElementHeight;
|
||||
}else if(coordinate.x < 0 && coordinate.y <= 0){
|
||||
// 3. quadrant
|
||||
left = centerDimension.left + centerDimension.a - this._config.gapX + coordinate.x - this._config.newElementWidth;
|
||||
top = centerDimension.top + Math.abs(coordinate.y);
|
||||
}else{
|
||||
// 4. quadrant
|
||||
left = centerDimension.left + centerDimension.a - this._config.gapX + coordinate.x;
|
||||
top = centerDimension.top + Math.abs(coordinate.y);
|
||||
}
|
||||
|
||||
// center horizontal for x = 0 coordinate (top and bottom element) --------------------------------
|
||||
if(coordinate.x === 0){
|
||||
left -= Math.round(this._config.newElementWidth / 2);
|
||||
}
|
||||
|
||||
// transform to grid coordinates (if grid snapping is enabled) ------------------------------------
|
||||
if(this._config.grid){
|
||||
let point = this._transformPointToGrid([left, top]);
|
||||
left = point[0];
|
||||
top = point[1];
|
||||
}
|
||||
|
||||
dim = {
|
||||
left: left,
|
||||
top: top,
|
||||
width: this._config.newElementWidth,
|
||||
height: this._config.newElementHeight
|
||||
};
|
||||
}
|
||||
|
||||
return dim;
|
||||
};
|
||||
|
||||
/**
|
||||
* calc overlapping percent of two given dimensions
|
||||
* @param dim1
|
||||
* @param dim2
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
this._percentCovered = (dim1, dim2) => {
|
||||
let percent = 0;
|
||||
|
||||
if(
|
||||
(dim1.left <= dim2.left) &&
|
||||
(dim1.top <= dim2.top) &&
|
||||
((dim1.left + dim1.width) >= (dim2.left + dim2.width)) &&
|
||||
((dim1.top + dim1.height) > (dim2.top + dim2.height))
|
||||
){
|
||||
// The whole thing is covering the whole other thing
|
||||
percent = 100;
|
||||
}else{
|
||||
// Only parts may be covered, calculate percentage
|
||||
dim1.right = dim1.left + dim1.width;
|
||||
dim1.bottom = dim1.top + dim1.height;
|
||||
dim2.right = dim2.left + dim2.width;
|
||||
dim2.bottom = dim2.top + dim2.height;
|
||||
|
||||
let l = Math.max(dim1.left, dim2.left);
|
||||
let r = Math.min(dim1.right, dim2.right);
|
||||
let t = Math.max(dim1.top, dim2.top);
|
||||
let b = Math.min(dim1.bottom, dim2.bottom);
|
||||
|
||||
if(b >= t && r >= l){
|
||||
percent = (((r - l) * (b - t)) / (dim2.width * dim2.height)) * 100;
|
||||
}
|
||||
}
|
||||
return percent;
|
||||
};
|
||||
|
||||
/**
|
||||
* checks whether dim1 is partially overlapped by any other element
|
||||
* @param dim1
|
||||
* @param dimensionContainer
|
||||
* @param allDimensions
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._isOverlapping = (dim1, dimensionContainer, allDimensions) => {
|
||||
let isOverlapping = false;
|
||||
if(dim1){
|
||||
if(this._percentCovered(dimensionContainer, dim1 ) === 100){
|
||||
// element is within parent container
|
||||
for(let dim2 of allDimensions){
|
||||
let percentCovered = this._percentCovered(dim1, dim2);
|
||||
if(percentCovered){
|
||||
isOverlapping = true;
|
||||
// render debug element
|
||||
this._showDebugElement(dim1, percentCovered);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
this._showDebugElement(dim1, 100);
|
||||
}
|
||||
}else{
|
||||
isOverlapping = true;
|
||||
}
|
||||
|
||||
return isOverlapping;
|
||||
};
|
||||
|
||||
/**
|
||||
* find all dimensions around a centerDimension that are not overlapped by other elements
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @param allDimensions
|
||||
* @param loops
|
||||
* @returns {Array}
|
||||
* @private
|
||||
*/
|
||||
this._findDimensions = (maxResults, steps, allDimensions, loops) => {
|
||||
let dimensions = [];
|
||||
let start = 0;
|
||||
let end = 360;
|
||||
let angle = end / steps;
|
||||
let dimensionContainer = this._getElementDimension(this._getContainer());
|
||||
steps = steps || 1;
|
||||
loops = loops || 1;
|
||||
|
||||
if(loops === 1){
|
||||
// check center element
|
||||
let centerDimension = this._getElementDimension(this._config.center);
|
||||
if(!this._isOverlapping(centerDimension, dimensionContainer, allDimensions)){
|
||||
dimensions.push({
|
||||
left: centerDimension.left,
|
||||
top: centerDimension.top,
|
||||
width: centerDimension.width,
|
||||
height: centerDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(centerDimension, 0);
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
}
|
||||
|
||||
// increase the "gab" between center element and potential found dimensions...
|
||||
// ... for each recursive loop call, to get an elliptical cycle beyond
|
||||
this._config.gapX = this._config.defaultGapX + (loops - 1) * 20;
|
||||
this._config.gapY = this._config.defaultGapY + (loops - 1) * 20;
|
||||
let centerDimension = this._getElementDimension(this._config.center);
|
||||
|
||||
while(maxResults > 0 && start < end){
|
||||
// get all potential coordinates on an eclipse around a given "centerElementDimension"
|
||||
let coordinate = this._getEllipseCoordinates(centerDimension, end);
|
||||
// transform relative x/y coordinate into a absolute 2D area
|
||||
let checkDimension = this._transformCoordinate(centerDimension, coordinate);
|
||||
if(!this._isOverlapping(checkDimension, dimensionContainer, allDimensions)){
|
||||
dimensions.push({
|
||||
left: checkDimension.left,
|
||||
top: checkDimension.top,
|
||||
width: checkDimension.width,
|
||||
height: checkDimension.height
|
||||
});
|
||||
// render debug element
|
||||
this._showDebugElement(checkDimension, 0);
|
||||
|
||||
maxResults--;
|
||||
}
|
||||
end -= angle;
|
||||
}
|
||||
|
||||
if(maxResults > 0 && loops < this._config.loops){
|
||||
loops++;
|
||||
steps *= 2;
|
||||
dimensions = dimensions.concat(this._findDimensions(maxResults, steps, allDimensions, loops));
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
};
|
||||
|
||||
/**
|
||||
* get container (parent) element
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
this._getContainer = () => {
|
||||
return this._config.container ? this._config.container : document.body;
|
||||
};
|
||||
|
||||
/**
|
||||
* render debug element into parent container
|
||||
* -> checks overlapping dimension with other elements
|
||||
* @param dimension
|
||||
* @param percentCovered
|
||||
* @private
|
||||
*/
|
||||
this._showDebugElement = (dimension, percentCovered) => {
|
||||
if(this._config.debug){
|
||||
let element = document.createElement('div');
|
||||
element.style.left = dimension.left + 'px';
|
||||
element.style.top = dimension.top + 'px';
|
||||
element.style.width = dimension.width + 'px';
|
||||
element.style.height = dimension.height + 'px';
|
||||
element.style.backgroundColor = Boolean(percentCovered) ? 'rgba(255,0,0,0.1)' : 'rgba(0,255,0,0.1)';
|
||||
element.innerHTML = Math.round(percentCovered * 100) / 100 + '%';
|
||||
element.classList.add(this._config.debugElementClass);
|
||||
this._getContainer().appendChild(element);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hide all debug elements
|
||||
* @private
|
||||
*/
|
||||
this._hideDebugElements = () => {
|
||||
let debugElements = this._getContainer().getElementsByClassName(this._config.debugElementClass);
|
||||
while(debugElements.length > 0){
|
||||
debugElements[0].parentNode.removeChild(debugElements[0]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// public functions ---------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* search for surrounding, non overlapping dimensions
|
||||
* @param maxResults
|
||||
* @param steps
|
||||
* @returns {Array}
|
||||
*/
|
||||
this.findNonOverlappingDimensions = (maxResults, steps) => {
|
||||
this._hideDebugElements();
|
||||
// element dimensions that exist and should be checked for overlapping
|
||||
let allDimensions = this._getAllElementDimensions();
|
||||
|
||||
return this._findDimensions(maxResults, steps, allDimensions);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return mouse coordinates from event
|
||||
* @param e
|
||||
* @returns {{x: number, y: number}}
|
||||
*/
|
||||
let getEventCoordinates = e => {
|
||||
let posX = 0;
|
||||
let posY = 0;
|
||||
|
||||
if(e.offsetX && e.offsetY){
|
||||
// Chrome
|
||||
posX = e.offsetX;
|
||||
posY = e.offsetY;
|
||||
}else if(e.originalEvent){
|
||||
// Firefox -> #415
|
||||
posX = e.originalEvent.layerX;
|
||||
posY = e.originalEvent.layerY;
|
||||
}
|
||||
|
||||
return {x: posX, y: posY};
|
||||
};
|
||||
|
||||
return {
|
||||
Position: Position,
|
||||
getEventCoordinates: getEventCoordinates
|
||||
};
|
||||
});
|
||||
583
public/js/v1.5.2/app/map/local.js
Normal file
583
public/js/v1.5.2/app/map/local.js
Normal file
@@ -0,0 +1,583 @@
|
||||
/**
|
||||
* map overlay functions for "Nearby" table
|
||||
* Created by Exodus on 13.04.2017.
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/util'
|
||||
], function($, Init, Util, MapUtil){
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
overlayClass: 'pf-map-overlay', // class for all map overlays
|
||||
overlayLocalClass: 'pf-map-overlay-local', // class for "local" overlay
|
||||
|
||||
// left section
|
||||
overlayLocalContentClass: 'pf-map-overlay-local-content', // class for left area - content
|
||||
overlayLocalHeadlineClass: 'pf-map-overlay-headline', // class for headline
|
||||
overlayLocalTableClass: 'pf-local-table', // class for local tables
|
||||
|
||||
// right section
|
||||
overlayLocalTriggerClass: 'pf-map-overlay-local-trigger', // class for open/close trigger icon
|
||||
overlayLocalOpenClass: 'pf-map-overlay-local-open', // class for open status
|
||||
overlayLocalMainClass: 'pf-map-overlay-local-main', // class for right area (always visible)
|
||||
overlayLocalUsersClass: 'pf-map-overlay-local-users', // class for active user count
|
||||
overlayLocalJumpsClass: 'pf-map-overlay-local-jumps', // class for jump distance for table results
|
||||
|
||||
// dataTable
|
||||
tableCellImageClass: 'pf-table-image-cell', // class for table "image" cells
|
||||
tableCellActionClass: 'pf-table-action-cell', // class for table "action" cells
|
||||
tableCellActionIconClass: 'pf-table-action-icon-cell', // class for table "action" icon (icon is part of cell content)
|
||||
|
||||
// toolbar
|
||||
toolbarClass: 'pf-map-overlay-toolbar', // class for toolbar - content
|
||||
toolbarIconClass: 'pf-map-overlay-toolbar-icon', // class for toolbar icon
|
||||
toolbarCheckboxClass: 'pf-map-overlay-toolbar-checkbox' // class for toolbar checkbox
|
||||
};
|
||||
|
||||
/**
|
||||
* checks whether overlay is currently open or not
|
||||
* @param overlay
|
||||
* @returns {*}
|
||||
*/
|
||||
let isOpen = (overlay) => {
|
||||
return overlay.hasClass(config.overlayLocalOpenClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* open overlay -> animation
|
||||
* @param overlay
|
||||
*/
|
||||
let openOverlay = (overlay) => {
|
||||
if( !isOpen(overlay) ){
|
||||
let overlayMain = overlay.find('.' + config.overlayLocalMainClass);
|
||||
overlayMain.find('.' + config.overlayLocalTriggerClass).addClass('right');
|
||||
overlay.addClass(config.overlayLocalOpenClass);
|
||||
|
||||
overlay.velocity({
|
||||
width: '350px'
|
||||
},{
|
||||
duration: Init.animationSpeed.mapOverlayLocal,
|
||||
easing: 'easeOut'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* close overlay -> animation
|
||||
* @param overlay
|
||||
*/
|
||||
let closeOverlay = (overlay) => {
|
||||
if( isOpen(overlay) ){
|
||||
let overlayMain = overlay.find('.' + config.overlayLocalMainClass);
|
||||
overlayMain.find('.' + config.overlayLocalTriggerClass).removeClass('right');
|
||||
overlay.removeClass(config.overlayLocalOpenClass);
|
||||
|
||||
overlay.velocity({
|
||||
width: '32px'
|
||||
},{
|
||||
duration: Init.animationSpeed.mapOverlayLocal,
|
||||
easing: 'easeOut'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* sets overlay observer
|
||||
* @param overlay
|
||||
* @param mapId
|
||||
*/
|
||||
let setOverlayObserver = (overlay, mapId) => {
|
||||
let overlayMain = overlay.find('.' + config.overlayLocalMainClass);
|
||||
|
||||
overlayMain.on('click', function(){
|
||||
let overlayMain = $(this).parent('.' + config.overlayLocalClass);
|
||||
let isOpenStatus = isOpen(overlayMain);
|
||||
|
||||
// store current state in indexDB (client)
|
||||
MapUtil.storeLocalData('map', mapId, 'showLocal', !isOpenStatus );
|
||||
|
||||
// trigger open/close
|
||||
if( isOpenStatus ){
|
||||
closeOverlay(overlay);
|
||||
}else{
|
||||
openOverlay(overlay);
|
||||
}
|
||||
});
|
||||
|
||||
overlayMain.initTooltips({
|
||||
container: 'body',
|
||||
placement: 'bottom'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* filter DataTable rows by column data and return rowIds
|
||||
* @param table
|
||||
* @param data
|
||||
* @param values
|
||||
* @param checkExistence
|
||||
*/
|
||||
let filterRows = (table, data = 'id', values = [], checkExistence = true) => {
|
||||
return table.rows().eq(0).filter( function(rowIdx){
|
||||
let rowExists = values.indexOf( table.row(rowIdx ).data()[data] ) !== -1;
|
||||
|
||||
if( !checkExistence ){
|
||||
rowExists = !rowExists;
|
||||
}
|
||||
|
||||
return rowExists;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the "headline" within the Overlay
|
||||
* @param overlay
|
||||
* @param systemData
|
||||
* @param characterAll
|
||||
* @param characterLocal
|
||||
*/
|
||||
let updateLocaleHeadline = (overlay, systemData, characterAll = 0, characterLocal = 0) => {
|
||||
let headlineElement = overlay.find('.' + config.overlayLocalHeadlineClass);
|
||||
let userCountElement = overlay.find('.' + config.overlayLocalUsersClass);
|
||||
|
||||
|
||||
let secClassBase = Util.getSecurityClassForSystem('security');
|
||||
let secClass = Util.getSecurityClassForSystem(systemData.security);
|
||||
|
||||
let childElements = headlineElement.children('span');
|
||||
childElements.eq(1).removeClass().addClass(
|
||||
[secClassBase, secClass].join(' ')
|
||||
).text(systemData.security);
|
||||
|
||||
childElements.eq(2).text(systemData.alias ? systemData.alias : systemData.name);
|
||||
|
||||
// update userCount for "near by" count -------------------------------------------------------------------
|
||||
if( characterAll > 0){
|
||||
userCountElement.toggleClass('txt-color-green', true).toggleClass('txt-color-red', false);
|
||||
}else{
|
||||
userCountElement.toggleClass('txt-color-green', false).toggleClass('txt-color-red', true);
|
||||
}
|
||||
userCountElement.text(characterAll);
|
||||
|
||||
// update userCount in current system ---------------------------------------------------------------------
|
||||
if( characterLocal > 0){
|
||||
childElements.eq(3).toggleClass('txt-color-green', true).toggleClass('txt-color-red', false);
|
||||
}else{
|
||||
childElements.eq(3).toggleClass('txt-color-green', false).toggleClass('txt-color-red', true);
|
||||
}
|
||||
childElements.eq(3).text(characterLocal);
|
||||
};
|
||||
|
||||
/**
|
||||
* updates all changed table rows
|
||||
* @param systemData
|
||||
* @param userData
|
||||
*/
|
||||
$.fn.updateLocalTable = function(systemData, userData){
|
||||
return this.each(function(){
|
||||
let overlay = $(this);
|
||||
let tableElement = overlay.find('.' + config.overlayLocalTableClass);
|
||||
let localTable = tableElement.DataTable();
|
||||
let mapId = systemData.mapId;
|
||||
|
||||
let characterAllIds = [];
|
||||
let characterLocalIds = [];
|
||||
|
||||
// system is on map (just for security check)
|
||||
for(let jumps in userData){
|
||||
if( userData.hasOwnProperty(jumps) ){
|
||||
jumps = parseInt(jumps);
|
||||
|
||||
for(let j = 0; j < userData[jumps].length; j++){
|
||||
// add jump distance
|
||||
userData[jumps][j].jumps = jumps;
|
||||
|
||||
let rowData = userData[jumps][j];
|
||||
|
||||
// check for existing rows
|
||||
let indexes = filterRows(localTable, 'id', [rowData.id]);
|
||||
|
||||
if(indexes.length > 0){
|
||||
// row exists -> update
|
||||
let changedRow = localTable.row( parseInt(indexes[0]) );
|
||||
let changedRowElement = changedRow.nodes().to$();
|
||||
|
||||
// remove tooltips
|
||||
changedRowElement.find('[title]').tooltip('hide').tooltip('destroy');
|
||||
|
||||
// update data
|
||||
changedRow.data(rowData);
|
||||
}else{
|
||||
// new row
|
||||
localTable.row.add(rowData);
|
||||
}
|
||||
|
||||
if(jumps === 0){
|
||||
characterLocalIds.push(rowData.id);
|
||||
}
|
||||
|
||||
characterAllIds.push(rowData.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove rows that no longer exists ----------------------------------------------------------------------
|
||||
let indexesRemove = filterRows(localTable, 'id', characterAllIds, false);
|
||||
localTable.rows(indexesRemove).remove();
|
||||
|
||||
localTable.draw();
|
||||
|
||||
// update system relevant data in overlay -----------------------------------------------------------------
|
||||
updateLocaleHeadline(overlay, systemData, characterAllIds.length, characterLocalIds.length);
|
||||
|
||||
// open Overlay -------------------------------------------------------------------------------------------
|
||||
if( !isOpen(overlay) ){
|
||||
let promiseStore = MapUtil.getLocaleData('map', mapId);
|
||||
promiseStore.then(function(dataStore){
|
||||
if(
|
||||
dataStore &&
|
||||
dataStore.showLocal
|
||||
){
|
||||
openOverlay(overlay);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init tooltip for a "DataTables" Cell
|
||||
* @param api
|
||||
* @param cell
|
||||
* @param titleSelector
|
||||
*/
|
||||
let initCellTooltip = (api, cell, titleSelector = '') => {
|
||||
$(cell).hover( function(e){
|
||||
let rowIdx = api.cell(cell).index().row;
|
||||
let rowData = api.row(rowIdx).data();
|
||||
|
||||
$(this).tooltip({
|
||||
container: 'body',
|
||||
title: Util.getObjVal(rowData, titleSelector),
|
||||
placement: 'left',
|
||||
delay: 100
|
||||
}).tooltip('show');
|
||||
}, function(e){
|
||||
$(this).tooltip('hide');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init all map local overlay on a "parent" element
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.initLocalOverlay = function(mapId){
|
||||
let parentElements = $(this);
|
||||
|
||||
require(['datatables.loader'], () => {
|
||||
parentElements.each(function(){
|
||||
let parentElement = $(this);
|
||||
|
||||
let overlay = $('<div>', {
|
||||
class: [config.overlayClass, config.overlayLocalClass].join(' ')
|
||||
});
|
||||
|
||||
let content = $('<div>', {
|
||||
class: [ 'text-right', config.overlayLocalContentClass].join(' ')
|
||||
});
|
||||
|
||||
// crate new route table
|
||||
let table = $('<table>', {
|
||||
class: ['compact', 'order-column', config.overlayLocalTableClass].join(' ')
|
||||
});
|
||||
|
||||
let overlayMain = $('<div>', {
|
||||
text: '',
|
||||
class: config.overlayLocalMainClass
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-chevron-down', 'fa-fw', 'pf-animate-rotate', config.overlayLocalTriggerClass].join(' ')
|
||||
}),
|
||||
$('<span>', {
|
||||
class: ['badge', 'txt-color', 'txt-color-red', config.overlayLocalUsersClass].join(' '),
|
||||
text: 0
|
||||
}),
|
||||
$('<div>', {
|
||||
class: config.overlayLocalJumpsClass
|
||||
}).append(
|
||||
$('<span>', {
|
||||
class: ['badge', 'txt-color', 'txt-color-grayLight'].join(' '),
|
||||
text: MapUtil.config.defaultLocalJumpRadius
|
||||
}).attr('title', 'jumps')
|
||||
)
|
||||
);
|
||||
|
||||
let headline = $('<div>', {
|
||||
class: config.overlayLocalHeadlineClass
|
||||
}).append(
|
||||
$('<span>', {
|
||||
html: 'Nearby ',
|
||||
class: 'pull-left'
|
||||
}),
|
||||
$('<span>'),
|
||||
$('<span>'),
|
||||
$('<span>', {
|
||||
class: ['badge', ' txt-color', 'txt-color-red'].join(' '),
|
||||
text: 0
|
||||
})
|
||||
);
|
||||
|
||||
content.append(headline);
|
||||
content.append(table);
|
||||
// toolbar not used for now
|
||||
// content.append(initToolbar());
|
||||
|
||||
overlay.append(overlayMain);
|
||||
overlay.append(content);
|
||||
|
||||
// set observer
|
||||
setOverlayObserver(overlay, mapId);
|
||||
|
||||
parentElement.append(overlay);
|
||||
|
||||
// init local table ---------------------------------------------------------------------------------------
|
||||
|
||||
table.on('draw.dt', function(e, settings){
|
||||
// init table tooltips
|
||||
$(this).find('td').initTooltips({
|
||||
container: 'body',
|
||||
placement: 'left'
|
||||
});
|
||||
|
||||
// hide pagination in case of only one page
|
||||
let paginationElement = overlay.find('.dataTables_paginate');
|
||||
let pageElements = paginationElement.find('span .paginate_button');
|
||||
if(pageElements.length <= 1){
|
||||
paginationElement.hide();
|
||||
}else{
|
||||
paginationElement.show();
|
||||
}
|
||||
});
|
||||
|
||||
// table init complete
|
||||
table.on('init.dt', function(){
|
||||
// init table head tooltips
|
||||
$(this).initTooltips({
|
||||
container: 'body',
|
||||
placement: 'top'
|
||||
});
|
||||
});
|
||||
|
||||
let localTable = table.DataTable( {
|
||||
pageLength: 13, // hint: if pagination visible => we need space to show it
|
||||
paging: true,
|
||||
lengthChange: false,
|
||||
ordering: true,
|
||||
order: [ 0, 'asc' ],
|
||||
info: false,
|
||||
searching: false,
|
||||
hover: false,
|
||||
responsive: false, // true "hides" some columns on init (why?)
|
||||
rowId: function(rowData){
|
||||
return 'pf-local-row_' + rowData.id; // characterId
|
||||
},
|
||||
language: {
|
||||
emptyTable: '<span>You are alone</span>'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
orderable: true,
|
||||
title: '<span title="jumps" data-toggle="tooltip"> </span>',
|
||||
width: '1px',
|
||||
className: [Util.config.helpDefaultClass, 'text-center'].join(' '),
|
||||
data: 'jumps',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
if(value === 0){
|
||||
value = '<i class="fas fa-map-marker-alt"></i>';
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let api = this.DataTable();
|
||||
initCellTooltip(api, cell, 'log.system.name');
|
||||
}
|
||||
},{
|
||||
targets: 1,
|
||||
orderable: false,
|
||||
title: '',
|
||||
width: '26px',
|
||||
className: [Util.config.helpDefaultClass, 'text-center', config.tableCellImageClass].join(' '),
|
||||
data: 'log.ship',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data.typeName;
|
||||
if(type === 'display'){
|
||||
value = '<img src="' + Init.url.ccpImageServer + '/Render/' + data.typeId + '_32.png"/>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let api = this.DataTable();
|
||||
initCellTooltip(api, cell, 'log.ship.typeName');
|
||||
}
|
||||
}, {
|
||||
targets: 2,
|
||||
orderable: true,
|
||||
title: 'ship name',
|
||||
width: '80px',
|
||||
data: 'log.ship',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data.name;
|
||||
if(type === 'display'){
|
||||
value = '<div class="' + MapUtil.config.tableCellEllipsisClass + ' ' + MapUtil.config.tableCellEllipsis80Class + '">' + data.name + '</div>';
|
||||
}
|
||||
return value;
|
||||
},
|
||||
sort: 'name'
|
||||
}
|
||||
},{
|
||||
targets: 3,
|
||||
orderable: true,
|
||||
title: 'pilot',
|
||||
data: 'name',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
value = '<div class="' + MapUtil.config.tableCellEllipsisClass + ' ' + MapUtil.config.tableCellEllipsis90Class + '">' + data + '</div>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 4,
|
||||
orderable: false,
|
||||
title: '',
|
||||
width: '10px',
|
||||
className: [Util.config.helpDefaultClass].join(' '),
|
||||
data: 'log',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = '';
|
||||
if(type === 'display'){
|
||||
if(data.station && data.station.id > 0){
|
||||
value = '<i class="fas fa-home"></i>';
|
||||
}else if(data.structure && data.structure.id > 0){
|
||||
value = '<i class="fas fa-industry"></i>';
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
let selector = '';
|
||||
if(cellData.station && cellData.station.id > 0){
|
||||
selector = 'log.station.name';
|
||||
}else if(cellData.structure && cellData.structure.id > 0){
|
||||
selector = 'log.structure.name';
|
||||
}
|
||||
let api = this.DataTable();
|
||||
initCellTooltip(api, cell, selector);
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
orderable: false,
|
||||
title: '<i title="open ingame" data-toggle="tooltip" class="fas fa-id-card text-right"></i>',
|
||||
width: '10px',
|
||||
className: [config.tableCellActionClass].join(' '),
|
||||
data: 'id',
|
||||
render: {
|
||||
_: (data, type, row, meta) => {
|
||||
let value = data;
|
||||
if(type === 'display'){
|
||||
value = '<i class="fas fa-id-card ' + config.tableCellActionIconClass + '"></i>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
// open character information window (ingame)
|
||||
$(cell).on('click', { tableApi: this.DataTable(), cellData: cellData }, function(e){
|
||||
let cellData = e.data.tableApi.cell(this).data();
|
||||
Util.openIngameWindow(e.data.cellData);
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
let initToolbar = () => {
|
||||
|
||||
let getCheckbox = (options) => {
|
||||
return $('<div>', {
|
||||
class: [config.toolbarCheckboxClass, 'checkbox'].join(' ')
|
||||
}).append(
|
||||
$('<input>', {
|
||||
type: 'checkbox',
|
||||
id: options.id,
|
||||
name: options.name,
|
||||
value: options.value,
|
||||
checked: 'checked'
|
||||
}),
|
||||
$('<label>',{
|
||||
'for': options.id,
|
||||
html: options.label
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
let toolbar = $('<div>', {
|
||||
class: [config.toolbarClass].join(' ')
|
||||
}).append(
|
||||
$('<i>', {
|
||||
class: ['fas', 'fa-fw', 'fa-lg', 'fa-filter', config.toolbarIconClass, 'pull-left'].join(' ')
|
||||
}),
|
||||
getCheckbox({
|
||||
id: 'test',
|
||||
name: 'filter_character_active',
|
||||
value: 1,
|
||||
checked: true,
|
||||
label: 'active'
|
||||
})
|
||||
);
|
||||
|
||||
return toolbar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear Overlay and "Reset"
|
||||
* @param mapId
|
||||
*/
|
||||
$.fn.clearLocalTable = function(mapId){
|
||||
return this.each(function(){
|
||||
let overlay = $(this);
|
||||
|
||||
// update locale overlay headline -------------------------------------------------------------------------
|
||||
updateLocaleHeadline(overlay, {
|
||||
name: 'unknown',
|
||||
security: ''
|
||||
});
|
||||
|
||||
// clear all table rows -----------------------------------------------------------------------------------
|
||||
let tableElement = overlay.find('.' + config.overlayLocalTableClass);
|
||||
let localTable = tableElement.DataTable();
|
||||
localTable.rows().remove().draw();
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
180
public/js/v1.5.2/app/map/magnetizing.js
Normal file
180
public/js/v1.5.2/app/map/magnetizing.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Map "magnetizing" feature
|
||||
* jsPlumb extension used: http://morrisonpitt.com/farahey/
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/map/util',
|
||||
'farahey'
|
||||
], function($, MapUtil){
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Cached current "Magnetizer" object
|
||||
* @type {Magnetizer}
|
||||
*/
|
||||
let m8 = null;
|
||||
|
||||
/**
|
||||
* init a jsPlumb (map) Element for "magnetised" function.
|
||||
* this is optional and prevents systems from being overlapped
|
||||
*/
|
||||
$.fn.initMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
let systems = mapContainer.getSystems();
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* get current system offset
|
||||
* @param system
|
||||
* @returns {{left, top}}
|
||||
* @private
|
||||
*/
|
||||
let _offset = function(system){
|
||||
|
||||
let _ = function(p){
|
||||
let v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
|
||||
return {
|
||||
left:_('left'),
|
||||
top:_('top')
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* set new system offset
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
let _setOffset = function(system, o){
|
||||
let markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 &&
|
||||
o.left <= 2300
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.left = o.left + 'px';
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 &&
|
||||
o.top <= 498
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.top = o.top + 'px';
|
||||
}
|
||||
|
||||
if(markAsUpdated === true){
|
||||
MapUtil.markAsChanged($(system));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* exclude current dragged element(s) from position update
|
||||
* @param id
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
let _dragFilter = function(id){
|
||||
return !$('#' + id).is('.jsPlumb_dragged, .pf-system-locked');
|
||||
};
|
||||
|
||||
let gridConstrain = function(gridX, gridY){
|
||||
return function(id, current, delta){
|
||||
if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){
|
||||
// active grid
|
||||
return {
|
||||
left:(gridX * Math.floor( (current[0] + delta.left) / gridX )) - current[0],
|
||||
top:(gridY * Math.floor( (current[1] + delta.top) / gridY )) - current[1]
|
||||
};
|
||||
}else{
|
||||
// no grid
|
||||
return delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// main init for "magnetize" feature ------------------------------------------------------
|
||||
m8 = new Magnetizer({
|
||||
container: mapContainer,
|
||||
getContainerPosition: function(c){
|
||||
return c.offset();
|
||||
},
|
||||
getPosition:_offset,
|
||||
getSize: function(system){
|
||||
return [ $(system).outerWidth(), $(system).outerHeight() ];
|
||||
},
|
||||
getId : function(system){
|
||||
return $(system).attr('id');
|
||||
},
|
||||
setPosition:_setOffset,
|
||||
elements: systems,
|
||||
filter: _dragFilter,
|
||||
padding: [6, 6],
|
||||
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension)
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.destroyMagnetizer = function(){
|
||||
let mapContainer = this;
|
||||
|
||||
// remove cached "magnetizer" instance
|
||||
m8 = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* update system positions for "all" systems that are effected by drag&drop
|
||||
* @param map
|
||||
* @param e
|
||||
*/
|
||||
let executeAtEvent = function(map, e){
|
||||
if(m8 !== null && e ){
|
||||
m8.executeAtEvent(e);
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* rearrange all systems of a map
|
||||
* needs "magnetization" to be active
|
||||
* @param map
|
||||
*/
|
||||
let executeAtCenter = function(map){
|
||||
if(m8 !== null){
|
||||
m8.executeAtCenter();
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* set/update elements for "magnetization"
|
||||
* -> (e.g. new systems was added)
|
||||
* @param map
|
||||
*/
|
||||
let setElements = function(map){
|
||||
if(m8 !== null){
|
||||
let mapContainer = $(map.getContainer());
|
||||
let systems = mapContainer.getSystems();
|
||||
m8.setElements(systems);
|
||||
|
||||
// re-arrange systems
|
||||
executeAtCenter(map);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
executeAtCenter: executeAtCenter,
|
||||
executeAtEvent: executeAtEvent,
|
||||
setElements: setElements
|
||||
};
|
||||
});
|
||||
3085
public/js/v1.5.2/app/map/map.js
Normal file
3085
public/js/v1.5.2/app/map/map.js
Normal file
File diff suppressed because it is too large
Load Diff
769
public/js/v1.5.2/app/map/overlay.js
Normal file
769
public/js/v1.5.2/app/map/overlay.js
Normal file
@@ -0,0 +1,769 @@
|
||||
/**
|
||||
* map overlay functions
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/util'
|
||||
], ($, Init, Util, MapUtil) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
logTimerCount: 3, // map log timer in seconds
|
||||
|
||||
// map overlay positions
|
||||
mapOverlayClass: 'pf-map-overlay', // class for all map overlays
|
||||
mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
|
||||
mapOverlayInfoClass: 'pf-map-overlay-info', // class for map overlay info e.g. map info
|
||||
overlayLocalClass: 'pf-map-overlay-local', // class for map overlay "local" table
|
||||
|
||||
// system
|
||||
systemHeadClass: 'pf-system-head', // class for system head
|
||||
|
||||
// overlay IDs
|
||||
connectionOverlayWhId: 'pf-map-connection-wh-overlay', // connection WH overlay ID (jsPlumb)
|
||||
connectionOverlayEolId: 'pf-map-connection-eol-overlay', // connection EOL overlay ID (jsPlumb)
|
||||
connectionOverlayArrowId: 'pf-map-connection-arrow-overlay', // connection Arrows overlay ID (jsPlumb)
|
||||
|
||||
endpointOverlayId: 'pf-map-endpoint-overlay', // endpoint overlay ID (jsPlumb)
|
||||
|
||||
// overlay classes
|
||||
componentOverlayClass: 'pf-map-component-overlay', // class for "normal size" overlay
|
||||
|
||||
connectionArrowOverlayClass: 'pf-map-connection-arrow-overlay', // class for "connection arrow" overlay
|
||||
connectionDiamondOverlayClass: 'pf-map-connection-diamond-overlay' // class for "connection diamond" overlay
|
||||
};
|
||||
|
||||
/**
|
||||
* get MapObject (jsPlumb) from mapElement
|
||||
* @param mapElement
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromMapElement = mapElement => {
|
||||
let Map = require('app/map/map');
|
||||
return Map.getMapInstance( mapElement.data('id') );
|
||||
};
|
||||
|
||||
/**
|
||||
* get map object (jsPlumb) from iconElement
|
||||
* @param overlayIcon
|
||||
* @returns {*}
|
||||
*/
|
||||
let getMapObjectFromOverlayIcon = overlayIcon => {
|
||||
let mapElement = Util.getMapElementFromOverlay(overlayIcon);
|
||||
|
||||
return getMapObjectFromMapElement( mapElement );
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlay to endpoint with signature data
|
||||
* @param endpoint
|
||||
* @param labelData
|
||||
*/
|
||||
let addEndpointOverlaySignatureLabel = (endpoint, labelData) => {
|
||||
let label = labelData.labels.join(', ');
|
||||
let name = labelData.names.join(', ');
|
||||
|
||||
endpoint.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: MapUtil.formatEndpointOverlaySignatureLabel(label),
|
||||
id: config.endpointOverlayId,
|
||||
cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
|
||||
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, label),
|
||||
events: {
|
||||
toggleSize: function(fullSize){
|
||||
let signatureName = this.getParameter('signatureName');
|
||||
if(fullSize && !this.getParameter('fullSize') && signatureName){
|
||||
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureName + '</span>');
|
||||
this.setParameter('fullSize', true);
|
||||
}else if(this.getParameter('fullSize')){
|
||||
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('label')));
|
||||
this.setParameter('fullSize', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
fullSize: false,
|
||||
label: label,
|
||||
signatureName: name
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
/**
|
||||
* add overlays to connections (signature based data)
|
||||
* @param connections
|
||||
* @param connectionsData
|
||||
*/
|
||||
let addConnectionsOverlay = (connections, connectionsData) => {
|
||||
let SystemSignatures = require('app/ui/module/system_signature');
|
||||
|
||||
// loop through all map connections (get from DOM)
|
||||
for(let connection of connections){
|
||||
let connectionId = connection.getParameter('connectionId');
|
||||
let sourceEndpoint = connection.endpoints[0];
|
||||
let targetEndpoint = connection.endpoints[1];
|
||||
|
||||
let signatureTypeData = {
|
||||
source: {
|
||||
names: [],
|
||||
labels: []
|
||||
},
|
||||
target: {
|
||||
names: [],
|
||||
labels: []
|
||||
}
|
||||
};
|
||||
|
||||
// ... find matching connectionData (from Ajax)
|
||||
for(let connectionData of connectionsData){
|
||||
if(connectionData.id === connectionId){
|
||||
signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
|
||||
// ... connection matched -> continue with next one
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add endpoint overlays ------------------------------------------------------
|
||||
addEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
|
||||
addEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
|
||||
|
||||
let sourceLabel = signatureTypeData.source.labels;
|
||||
let targetLabel = signatureTypeData.target.labels;
|
||||
|
||||
// add arrow (connection) overlay that points from "XXX" => "K162" ------------
|
||||
let overlayType = 'Diamond'; // not specified
|
||||
let arrowDirection = 1;
|
||||
|
||||
if(
|
||||
(sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
|
||||
(
|
||||
sourceLabel.length > 0 && targetLabel.length > 0 &&
|
||||
sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
|
||||
)
|
||||
){
|
||||
// unknown direction
|
||||
overlayType = 'Diamond'; // not specified
|
||||
arrowDirection = 1;
|
||||
}else if(
|
||||
(sourceLabel.indexOf('K162') !== -1) ||
|
||||
(sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
|
||||
){
|
||||
// convert default arrow direction
|
||||
overlayType = 'Arrow';
|
||||
arrowDirection = -1;
|
||||
}else{
|
||||
// default arrow direction is fine
|
||||
overlayType = 'Arrow';
|
||||
arrowDirection = 1;
|
||||
}
|
||||
|
||||
connection.addOverlay([
|
||||
overlayType,
|
||||
{
|
||||
width: 12,
|
||||
length: 15,
|
||||
location: 0.5,
|
||||
foldback: 0.85,
|
||||
direction: arrowDirection,
|
||||
id: config.connectionOverlayArrowId,
|
||||
cssClass: (overlayType === 'Arrow') ? config.connectionArrowOverlayClass : config.connectionDiamondOverlayClass
|
||||
}
|
||||
]);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* remove overviews from a Tooltip
|
||||
* @param endpoint
|
||||
* @param i
|
||||
*/
|
||||
let removeEndpointOverlay = (endpoint, i) => {
|
||||
endpoint.removeOverlays(config.endpointOverlayId);
|
||||
};
|
||||
|
||||
/**
|
||||
* format json object with "time parts" into string
|
||||
* @param parts
|
||||
* @returns {string}
|
||||
*/
|
||||
let formatTimeParts = parts => {
|
||||
let label = '';
|
||||
if(parts.days){
|
||||
label += parts.days + 'd ';
|
||||
}
|
||||
label += ('00' + parts.hours).slice(-2);
|
||||
label += ':' + ('00' + parts.min).slice(-2);
|
||||
return label;
|
||||
};
|
||||
|
||||
/**
|
||||
* hide default icon and replace it with "loading" icon
|
||||
* @param iconElement
|
||||
*/
|
||||
let showLoading = iconElement => {
|
||||
iconElement = $(iconElement);
|
||||
let dataName = 'default-icon';
|
||||
let defaultIconClass = iconElement.data(dataName);
|
||||
|
||||
// get default icon class
|
||||
if( !defaultIconClass ){
|
||||
// index 0 == 'fa-fw', index 1 == IconName
|
||||
defaultIconClass = $(iconElement).attr('class').match(/\bfa-\S*/g)[1];
|
||||
iconElement.data(dataName, defaultIconClass);
|
||||
}
|
||||
|
||||
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
|
||||
};
|
||||
|
||||
/**
|
||||
* hide "loading" icon and replace with default icon
|
||||
* @param iconElement
|
||||
*/
|
||||
let hideLoading = iconElement => {
|
||||
iconElement = $(iconElement);
|
||||
let dataName = 'default-icon';
|
||||
let defaultIconClass = iconElement.data(dataName);
|
||||
|
||||
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
|
||||
};
|
||||
|
||||
/**
|
||||
* git signature data that is linked to a connection for a mapId
|
||||
* @param mapElement
|
||||
* @param connections
|
||||
* @param callback
|
||||
*/
|
||||
let getConnectionSignatureData = (mapElement, connections, callback) => {
|
||||
let mapOverlay = $(mapElement).getMapOverlay('info');
|
||||
let overlayConnectionIcon = mapOverlay.find('.pf-map-overlay-endpoint');
|
||||
|
||||
showLoading(overlayConnectionIcon);
|
||||
|
||||
let requestData = {
|
||||
mapId: mapElement.data('id'),
|
||||
addData : ['signatures'],
|
||||
filterData : ['signatures']
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.getMapConnectionData,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
mapElement: mapElement,
|
||||
connections: connections,
|
||||
overlayConnectionIcon: overlayConnectionIcon
|
||||
}
|
||||
}).done(function(connectionsData){
|
||||
// hide all connection before add them (refresh)
|
||||
this.mapElement.hideEndpointOverlays();
|
||||
// ... add overlays
|
||||
callback(this.connections, connectionsData);
|
||||
}).always(function(){
|
||||
hideLoading(this.overlayConnectionIcon);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* showEndpointOverlays
|
||||
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
|
||||
*/
|
||||
$.fn.showEndpointOverlays = function(){
|
||||
let mapElement = $(this);
|
||||
let map = getMapObjectFromMapElement(mapElement);
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', undefined, true);
|
||||
|
||||
// get connection signature information ---------------------------------------
|
||||
getConnectionSignatureData(mapElement, connections, addConnectionsOverlay);
|
||||
};
|
||||
|
||||
/**
|
||||
* hideEndpointOverlays
|
||||
* -> see showEndpointOverlays()
|
||||
*/
|
||||
$.fn.hideEndpointOverlays = function(){
|
||||
let map = getMapObjectFromMapElement($(this));
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
|
||||
|
||||
for(let connection of connections){
|
||||
connection.removeOverlays(config.connectionOverlayArrowId);
|
||||
connection.endpoints.forEach(removeEndpointOverlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Overlay options (all available map options shown in overlay)
|
||||
* "active": (active || hover) indicated whether an icon/option
|
||||
* is marked as "active".
|
||||
* "active": Makes icon active when visible
|
||||
* "hover": Make icon active on hover
|
||||
*/
|
||||
let options = {
|
||||
filter: {
|
||||
title: 'active filter',
|
||||
trigger: 'active',
|
||||
class: 'pf-map-overlay-filter',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-filter'],
|
||||
onClick: function(e){
|
||||
// clear all filter
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
|
||||
MapUtil.storeLocalData('map', mapElement.data('id'), 'filterScopes', []);
|
||||
MapUtil.filterMapByScopes(map, []);
|
||||
}
|
||||
},
|
||||
mapSnapToGrid: {
|
||||
title: 'active grid',
|
||||
trigger: 'active',
|
||||
class: 'pf-map-overlay-grid',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-th']
|
||||
},
|
||||
mapMagnetizer: {
|
||||
title: 'active magnetizer',
|
||||
trigger: 'active',
|
||||
class: 'pf-map-overlay-magnetizer',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-magnet']
|
||||
},
|
||||
systemRegion: {
|
||||
title: 'show regions',
|
||||
trigger: 'hover',
|
||||
class: 'pf-map-overlay-region',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-tags'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
mapElement.find('.' + config.systemHeadClass).each(function(){
|
||||
let systemHead = $(this);
|
||||
// init popover if not already exists
|
||||
if(!systemHead.data('bs.popover')){
|
||||
let system = systemHead.parent();
|
||||
systemHead.popover({
|
||||
placement: 'right',
|
||||
html: true,
|
||||
trigger: 'manual',
|
||||
container: mapElement,
|
||||
title: false,
|
||||
content: Util.getSystemRegionTable(
|
||||
system.data('region'),
|
||||
system.data('faction') || null
|
||||
)
|
||||
});
|
||||
}
|
||||
systemHead.setPopoverSmall();
|
||||
systemHead.popover('show');
|
||||
});
|
||||
},
|
||||
out: function(e){
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
mapElement.find('.' + config.systemHeadClass).popover('hide');
|
||||
}
|
||||
}
|
||||
},
|
||||
mapEndpoint: {
|
||||
title: 'refresh signature overlays',
|
||||
trigger: 'refresh',
|
||||
class: 'pf-map-overlay-endpoint',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-link'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let mapElement = Util.getMapElementFromOverlay(this);
|
||||
mapElement.showEndpointOverlays();
|
||||
},
|
||||
out: function(e){
|
||||
// just "refresh" on hover
|
||||
}
|
||||
}
|
||||
},
|
||||
mapCompact: {
|
||||
title: 'compact layout',
|
||||
trigger: 'active',
|
||||
class: 'pf-map-overlay-compact',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-compress']
|
||||
},
|
||||
connection: {
|
||||
title: 'WH data',
|
||||
trigger: 'hover',
|
||||
class: 'pf-map-overlay-connection-wh',
|
||||
iconClass: ['fas', 'fa-fw', 'fa-fighter-jet'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
|
||||
let serverDate = Util.getServerTime();
|
||||
|
||||
// show connection overlays ---------------------------------------------------
|
||||
for(let connection of connections){
|
||||
let createdTimestamp = connection.getParameter('created');
|
||||
let updatedTimestamp = connection.getParameter('updated');
|
||||
|
||||
let createdDate = Util.convertTimestampToServerTime(createdTimestamp);
|
||||
let updatedDate = Util.convertTimestampToServerTime(updatedTimestamp);
|
||||
|
||||
let createdDiff = Util.getTimeDiffParts(createdDate, serverDate);
|
||||
let updatedDiff = Util.getTimeDiffParts(updatedDate, serverDate);
|
||||
|
||||
// format overlay label
|
||||
let labels = [
|
||||
'<i class="fas fa-fw fa-plus-square"></i> ' + formatTimeParts(createdDiff),
|
||||
'<i class="fas fa-fw fa-pen-square"></i> ' + formatTimeParts(updatedDiff)
|
||||
];
|
||||
|
||||
// add label overlay ------------------------------------------------------
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: labels.join('<br>'),
|
||||
id: config.connectionOverlayWhId,
|
||||
cssClass: [config.componentOverlayClass, 'small'].join(' '),
|
||||
location: 0.35
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
out: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
|
||||
|
||||
for(let connection of connections){
|
||||
connection.removeOverlays(config.connectionOverlayWhId);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
connectionEol: {
|
||||
title: 'EOL timer',
|
||||
trigger: 'hover',
|
||||
class: 'pf-map-overlay-connection-eol',
|
||||
iconClass: ['far', 'fa-fw', 'fa-clock'],
|
||||
hoverIntent: {
|
||||
over: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
|
||||
let serverDate = Util.getServerTime();
|
||||
|
||||
for(let connection of connections){
|
||||
let eolTimestamp = connection.getParameter('eolUpdated');
|
||||
let eolDate = Util.convertTimestampToServerTime(eolTimestamp);
|
||||
let diff = Util.getTimeDiffParts(eolDate, serverDate);
|
||||
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
label: '<i class="far fa-fw fa-clock"></i> ' + formatTimeParts(diff),
|
||||
id: config.connectionOverlayEolId,
|
||||
cssClass: [config.componentOverlayClass, 'eol'].join(' '),
|
||||
location: 0.25
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
out: function(e){
|
||||
let map = getMapObjectFromOverlayIcon(this);
|
||||
let MapUtil = require('app/map/util');
|
||||
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
|
||||
|
||||
for(let connection of connections){
|
||||
connection.removeOverlay(config.connectionOverlayEolId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get map overlay element by type e.g. timer/counter, info - overlay
|
||||
* @param overlayType
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMapOverlay = function(overlayType){
|
||||
let mapWrapperElement = $(this).parents('.' + MapUtil.config.mapWrapperClass);
|
||||
|
||||
let mapOverlay = null;
|
||||
switch(overlayType){
|
||||
case 'timer':
|
||||
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
|
||||
break;
|
||||
case 'info':
|
||||
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayInfoClass);
|
||||
break;
|
||||
case 'local':
|
||||
mapOverlay = mapWrapperElement.find('.' + config.overlayLocalClass);
|
||||
break;
|
||||
}
|
||||
|
||||
return mapOverlay;
|
||||
};
|
||||
|
||||
/**
|
||||
* draws the map update counter to the map overlay timer
|
||||
* @param percent
|
||||
* @param value
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.setMapUpdateCounter = function(percent, value){
|
||||
|
||||
let mapOverlayTimer = $(this);
|
||||
|
||||
// check if counter already exists
|
||||
let counterChart = mapOverlayTimer.getMapCounter();
|
||||
|
||||
if(counterChart.length === 0){
|
||||
// create new counter
|
||||
|
||||
counterChart = $('<div>', {
|
||||
class: [Init.classes.pieChart.class, Init.classes.pieChart.pieChartMapCounterClass].join(' ')
|
||||
}).attr('data-percent', percent).append(
|
||||
$('<span>', {
|
||||
text: value
|
||||
})
|
||||
);
|
||||
|
||||
mapOverlayTimer.append(counterChart);
|
||||
|
||||
// init counter
|
||||
counterChart.initMapUpdateCounter();
|
||||
|
||||
// set tooltip
|
||||
mapOverlayTimer.attr('data-placement', 'left');
|
||||
mapOverlayTimer.attr('title', 'update counter');
|
||||
mapOverlayTimer.tooltip();
|
||||
}
|
||||
|
||||
return counterChart;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the map counter chart from overlay
|
||||
* @returns {JQuery|*|T|{}|jQuery}
|
||||
*/
|
||||
$.fn.getMapCounter = function(){
|
||||
return $(this).find('.' + Init.classes.pieChart.pieChartMapCounterClass);
|
||||
};
|
||||
|
||||
$.fn.getMapOverlayInterval = function(){
|
||||
return $(this).getMapOverlay('timer').getMapCounter().data('interval');
|
||||
};
|
||||
|
||||
/**
|
||||
* start the map update counter or reset
|
||||
*/
|
||||
$.fn.startMapUpdateCounter = function(){
|
||||
|
||||
let mapOverlayTimer = $(this);
|
||||
let counterChart = mapOverlayTimer.getMapCounter();
|
||||
|
||||
let maxSeconds = config.logTimerCount;
|
||||
|
||||
let counterChartLabel = counterChart.find('span');
|
||||
|
||||
let percentPerCount = 100 / maxSeconds;
|
||||
|
||||
// update counter
|
||||
let updateChart = function(tempSeconds){
|
||||
let pieChart = counterChart.data('easyPieChart');
|
||||
|
||||
if(pieChart !== undefined){
|
||||
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
|
||||
}
|
||||
counterChartLabel.text(tempSeconds);
|
||||
};
|
||||
|
||||
// main timer function is called on any counter update
|
||||
let timer = function(mapUpdateCounter){
|
||||
// decrease timer
|
||||
let currentSeconds = counterChart.data('currentSeconds');
|
||||
currentSeconds--;
|
||||
counterChart.data('currentSeconds', currentSeconds);
|
||||
|
||||
if(currentSeconds >= 0){
|
||||
// update counter
|
||||
updateChart(currentSeconds);
|
||||
}else{
|
||||
// hide counter and reset
|
||||
clearInterval(mapUpdateCounter);
|
||||
|
||||
mapOverlayTimer.velocity('transition.whirlOut', {
|
||||
duration: Init.animationSpeed.mapOverlay,
|
||||
complete: function(){
|
||||
counterChart.data('interval', false);
|
||||
Util.getMapElementFromOverlay(mapOverlayTimer).trigger('pf:unlocked');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// get current seconds (in case the timer is already running)
|
||||
let currentSeconds = counterChart.data('currentSeconds');
|
||||
|
||||
// start values for timer and chart
|
||||
counterChart.data('currentSeconds', maxSeconds);
|
||||
updateChart(maxSeconds);
|
||||
|
||||
if(
|
||||
currentSeconds === undefined ||
|
||||
currentSeconds < 0
|
||||
){
|
||||
// start timer
|
||||
let mapUpdateCounter = setInterval(() => {
|
||||
timer(mapUpdateCounter);
|
||||
}, 1000);
|
||||
|
||||
// store counter interval
|
||||
counterChart.data('interval', mapUpdateCounter);
|
||||
|
||||
// show overlay
|
||||
if(mapOverlayTimer.is(':hidden')){
|
||||
mapOverlayTimer.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* update (show/hide) a overlay icon in the "info"-overlay
|
||||
* show/hide the overlay itself is no icons are visible
|
||||
* @param option
|
||||
* @param viewType
|
||||
*/
|
||||
$.fn.updateOverlayIcon = function(option, viewType){
|
||||
let mapOverlayInfo = $(this);
|
||||
|
||||
let showOverlay = false;
|
||||
|
||||
let mapOverlayIconClass = options[option].class;
|
||||
|
||||
// look for the overlay icon that should be updated
|
||||
let iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
|
||||
|
||||
if(iconElement){
|
||||
if(viewType === 'show'){
|
||||
showOverlay = true;
|
||||
|
||||
// check "trigger" and mark as "active"
|
||||
if(
|
||||
options[option].trigger === 'active' ||
|
||||
options[option].trigger === 'refresh'
|
||||
){
|
||||
iconElement.addClass('active');
|
||||
}
|
||||
|
||||
// check if icon is not already visible
|
||||
// -> prevents unnecessary "show" animation
|
||||
if( !iconElement.data('visible') ){
|
||||
// display animation for icon
|
||||
iconElement.velocity({
|
||||
opacity: [0.8, 0],
|
||||
scale: [1, 0],
|
||||
width: ['20px', 0],
|
||||
height: ['20px', 0],
|
||||
marginRight: ['10px', 0]
|
||||
},{
|
||||
duration: 240,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
|
||||
iconElement.data('visible', true);
|
||||
}
|
||||
}else if(viewType === 'hide'){
|
||||
// check if icon is not already visible
|
||||
// -> prevents unnecessary "hide" animation
|
||||
if(iconElement.data('visible')){
|
||||
iconElement.removeClass('active').velocity('reverse');
|
||||
iconElement.data('visible', false);
|
||||
}
|
||||
|
||||
// check if there is any visible icon remaining
|
||||
let visibleIcons = mapOverlayInfo.find('i:visible');
|
||||
if(visibleIcons.length > 0){
|
||||
showOverlay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show the entire overlay if there is at least one active icon
|
||||
if(
|
||||
showOverlay === true &&
|
||||
mapOverlayInfo.is(':hidden')
|
||||
){
|
||||
// show overlay
|
||||
mapOverlayInfo.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
|
||||
}else if(
|
||||
showOverlay === false &&
|
||||
mapOverlayInfo.is(':visible')
|
||||
){
|
||||
// hide overlay
|
||||
mapOverlayInfo.velocity('stop').velocity('transition.whirlOut', { duration: Init.animationSpeed.mapOverlay });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init all map overlays on a "parent" element
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.initMapOverlays = function(){
|
||||
return this.each(function(){
|
||||
let parentElement = $(this);
|
||||
|
||||
let mapOverlayTimer = $('<div>', {
|
||||
class: [config.mapOverlayClass, config.mapOverlayTimerClass].join(' ')
|
||||
});
|
||||
parentElement.append(mapOverlayTimer);
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// add map overlay info. after scrollbar is initialized
|
||||
let mapOverlayInfo = $('<div>', {
|
||||
class: [config.mapOverlayClass, config.mapOverlayInfoClass].join(' ')
|
||||
});
|
||||
|
||||
// add all overlay elements
|
||||
for(let prop in options){
|
||||
if(options.hasOwnProperty(prop)){
|
||||
let icon = $('<i>', {
|
||||
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
|
||||
}).attr('title', options[prop].title).tooltip({
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
delay: 150
|
||||
});
|
||||
|
||||
// add "hover" action for some icons
|
||||
if(
|
||||
options[prop].trigger === 'hover' ||
|
||||
options[prop].trigger === 'refresh'
|
||||
){
|
||||
icon.hoverIntent(options[prop].hoverIntent);
|
||||
}
|
||||
|
||||
// add "click" handler for some icons
|
||||
if(options[prop].hasOwnProperty('onClick')){
|
||||
icon.on('click', options[prop].onClick);
|
||||
}
|
||||
|
||||
mapOverlayInfo.append(icon);
|
||||
}
|
||||
}
|
||||
parentElement.append(mapOverlayInfo);
|
||||
|
||||
// reset map update timer
|
||||
mapOverlayTimer.setMapUpdateCounter(100, config.logTimerCount);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
endpointOverlayId: config.endpointOverlayId
|
||||
};
|
||||
|
||||
});
|
||||
109
public/js/v1.5.2/app/map/scrollbar.js
Normal file
109
public/js/v1.5.2/app/map/scrollbar.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Created by Exodus on 26.06.2016.
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'mousewheel',
|
||||
'customScrollbar'
|
||||
], ($, Init, Util) => {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* init map scrollbar
|
||||
* @param config
|
||||
*/
|
||||
$.fn.initCustomScrollbar = function(config){
|
||||
|
||||
// default config -------------------------------------------------------------------------
|
||||
let defaultConfig = {
|
||||
axis: 'yx',
|
||||
theme: 'light-3' ,
|
||||
scrollInertia: 300,
|
||||
autoExpandScrollbar: false,
|
||||
scrollButtons:{
|
||||
enable: true,
|
||||
scrollAmount: 30,
|
||||
scrollType: 'stepless'
|
||||
},
|
||||
callbacks: {
|
||||
onTotalScrollOffset: 0,
|
||||
onTotalScrollBackOffset: 0,
|
||||
alwaysTriggerOffsets: true
|
||||
},
|
||||
|
||||
advanced: {
|
||||
updateOnContentResize: true,
|
||||
autoExpandHorizontalScroll: true,
|
||||
//autoExpandHorizontalScroll: 2,
|
||||
autoScrollOnFocus: 'div',
|
||||
},
|
||||
mouseWheel: {
|
||||
enable: false, // scroll wheel currently disabled
|
||||
scrollAmount: 'auto',
|
||||
axis: 'x',
|
||||
preventDefault: true
|
||||
},
|
||||
keyboard: {
|
||||
enable: false, // not working with pathfinder "shortcuts"
|
||||
scrollType: 'stepless',
|
||||
scrollAmount: 'auto'
|
||||
},
|
||||
scrollbarPosition: 'inside',
|
||||
autoDraggerLength: true,
|
||||
autoHideScrollbar: false
|
||||
};
|
||||
|
||||
// init -----------------------------------------------------------------------------------
|
||||
config = $.extend(true, {}, defaultConfig, config);
|
||||
|
||||
return this.each(function(){
|
||||
let mapWrapperElement = $(this);
|
||||
|
||||
// prevent multiple initialization
|
||||
mapWrapperElement.mCustomScrollbar('destroy');
|
||||
|
||||
// init custom scrollbars
|
||||
mapWrapperElement.mCustomScrollbar(config);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* scroll to a specific position on map
|
||||
* demo: http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/scrollTo_demo.html
|
||||
* @param position
|
||||
*/
|
||||
$.fn.scrollToPosition = function(position){
|
||||
return this.each(function(){
|
||||
$(this).mCustomScrollbar('scrollTo', position);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* scroll to a specific system on map
|
||||
* -> subtract some offset for tooltips/connections
|
||||
* @param position
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.scrollToSystem = function(position){
|
||||
position = getOffsetPosition(position, {x: -15, y: -35});
|
||||
return this.each(function(){
|
||||
$(this).mCustomScrollbar('scrollTo', position);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add/subtract offset coordinates from position
|
||||
* -> no negative values returned
|
||||
* @param position
|
||||
* @param offset
|
||||
* @returns {{x: number, y: number}}
|
||||
*/
|
||||
let getOffsetPosition = (position, offset) => {
|
||||
return {
|
||||
x: Math.max(0, position.x + offset.x),
|
||||
y: Math.max(0, position.y + offset.y)
|
||||
};
|
||||
};
|
||||
});
|
||||
817
public/js/v1.5.2/app/map/system.js
Normal file
817
public/js/v1.5.2/app/map/system.js
Normal file
@@ -0,0 +1,817 @@
|
||||
/**
|
||||
* map system functions
|
||||
*/
|
||||
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox',
|
||||
'app/map/util',
|
||||
'app/map/layout'
|
||||
], ($, Init, Util, bootbox, MapUtil, Layout) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
newSystemOffset: {
|
||||
x: 130,
|
||||
y: 0
|
||||
},
|
||||
|
||||
mapClass: 'pf-map', // class for all maps
|
||||
|
||||
systemHeadInfoClass: 'pf-system-head-info', // class for system info
|
||||
systemHeadInfoLeftClass: 'pf-system-head-info-left', // class for left system info
|
||||
systemHeadInfoRightClass: 'pf-system-head-info-right', // class for right system info
|
||||
|
||||
systemActiveClass: 'pf-system-active', // class for an active system on a map
|
||||
systemTooltipInnerIdPrefix: 'pf-system-tooltip-inner-', // id prefix for system tooltip content
|
||||
systemTooltipInnerClass: 'pf-system-tooltip-inner', // class for system tooltip content
|
||||
|
||||
// dialogs
|
||||
dialogSystemId: 'pf-system-dialog', // id for system dialog
|
||||
dialogSystemSelectClass: 'pf-system-dialog-select', // class for system select element
|
||||
dialogSystemStatusSelectId: 'pf-system-dialog-status-select', // id for "status" select
|
||||
dialogSystemLockId: 'pf-system-dialog-lock', // id for "locked" checkbox
|
||||
dialogSystemRallyId: 'pf-system-dialog-rally', // id for "rally" checkbox
|
||||
|
||||
dialogSystemSectionInfoId: 'pf-system-dialog-section-info', // id for "info" section element
|
||||
dialogSystemSectionInfoStatusId: 'pf-system-dialog-section-info-status', // id for "status" message in "info" element
|
||||
dialogSystemAliasId: 'pf-system-dialog-alias', // id for "alias" static element
|
||||
dialogSystemDescriptionId: 'pf-system-dialog-description', // id for "description" static element
|
||||
dialogSystemCreatedId: 'pf-system-dialog-created', // id for "created" static element
|
||||
dialogSystemUpdatedId: 'pf-system-dialog-updated', // id for "updated" static element
|
||||
|
||||
dialogRallyId: 'pf-rally-dialog', // id for "Rally point" dialog
|
||||
dialogRallyPokeDesktopId: 'pf-rally-dialog-poke-desktop', // id for "desktop" poke checkbox
|
||||
dialogRallyPokeSlackId: 'pf-rally-dialog-poke-slack', // id for "Slack" poke checkbox
|
||||
dialogRallyPokeDiscordId: 'pf-rally-dialog-poke-discord', // id for "Discord" poke checkbox
|
||||
dialogRallyPokeMailId: 'pf-rally-dialog-poke-mail', // id for "mail" poke checkbox
|
||||
dialogRallyMessageId: 'pf-rally-dialog-message', // id for "message" textarea
|
||||
|
||||
dialogRallyMessageDefault: '' +
|
||||
'I need some help!\n\n' +
|
||||
'- Potential PvP options around\n' +
|
||||
'- DPS and Logistic ships needed'
|
||||
};
|
||||
|
||||
/**
|
||||
* open "new system" dialog and add the system to map
|
||||
* optional the new system is connected to a "sourceSystem" (if available)
|
||||
* @param map
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
let showNewSystemDialog = (map, options, callback) => {
|
||||
let mapContainer = $(map.getContainer());
|
||||
let mapId = mapContainer.data('id');
|
||||
|
||||
/**
|
||||
* update new system dialog with some "additional" data
|
||||
* -> if system was mapped before
|
||||
* @param dialogElement
|
||||
* @param systemData
|
||||
*/
|
||||
let updateDialog = (dialogElement, systemData = null) => {
|
||||
let labelEmpty = '<span class="editable-empty">empty</span>';
|
||||
let labelUnknown = '<span class="editable-empty">unknown</span>';
|
||||
let labelExist = '<span class="txt-color txt-color-success">loaded</span>';
|
||||
|
||||
let showInfoHeadline = 'fadeOut';
|
||||
let showInfoSection = 'hide';
|
||||
let info = labelEmpty;
|
||||
|
||||
let statusId = false; // -> no value change
|
||||
let alias = labelEmpty;
|
||||
let description = labelEmpty;
|
||||
let createdTime = labelUnknown;
|
||||
let updatedTime = labelUnknown;
|
||||
|
||||
if(systemData){
|
||||
// system data found for selected system
|
||||
showInfoHeadline = 'fadeIn';
|
||||
showInfoSection = 'show';
|
||||
info = labelExist;
|
||||
statusId = parseInt(Util.getObjVal(systemData, 'status.id')) || statusId;
|
||||
alias = systemData.alias.length ? Util.htmlEncode(systemData.alias) : alias;
|
||||
description = systemData.description.length ? systemData.description : description;
|
||||
|
||||
let dateCreated = new Date(systemData.created.created * 1000);
|
||||
let dateUpdated = new Date(systemData.updated.updated * 1000);
|
||||
let dateCreatedUTC = Util.convertDateToUTC(dateCreated);
|
||||
let dateUpdatedUTC = Util.convertDateToUTC(dateUpdated);
|
||||
|
||||
createdTime = Util.convertDateToString(dateCreatedUTC);
|
||||
updatedTime = Util.convertDateToString(dateUpdatedUTC);
|
||||
|
||||
}else if(systemData === null){
|
||||
// no system found for selected system
|
||||
showInfoHeadline = 'fadeIn';
|
||||
}
|
||||
|
||||
// update new system dialog with new default data
|
||||
dialogElement.find('#' + config.dialogSystemSectionInfoStatusId).html(info);
|
||||
if(statusId !== false){
|
||||
dialogElement.find('#' + config.dialogSystemStatusSelectId).val(statusId).trigger('change');
|
||||
}
|
||||
dialogElement.find('#' + config.dialogSystemAliasId).html(alias);
|
||||
dialogElement.find('#' + config.dialogSystemDescriptionId).html(description);
|
||||
dialogElement.find('#' + config.dialogSystemCreatedId).html('<i class="fas fa-fw fa-plus"></i> ' + createdTime);
|
||||
dialogElement.find('#' + config.dialogSystemUpdatedId).html('<i class="fas fa-fw fa-pen"></i> ' + updatedTime);
|
||||
dialogElement.find('[data-target="#' + config.dialogSystemSectionInfoId + '"]').velocity('stop').velocity(showInfoHeadline, {duration: 120});
|
||||
dialogElement.find('[data-type="spinner"]').removeClass('in');
|
||||
dialogElement.find('#' + config.dialogSystemSectionInfoId).collapse(showInfoSection);
|
||||
};
|
||||
|
||||
/**
|
||||
* request system data from server for persistent data -> update dialog
|
||||
* @param dialogElement
|
||||
* @param mapId
|
||||
* @param systemId
|
||||
*/
|
||||
let requestSystemData = (dialogElement, mapId, systemId) => {
|
||||
// show loading animation
|
||||
dialogElement.find('[data-type="spinner"]').addClass('in');
|
||||
|
||||
Util.request('GET', 'system', systemId, {mapId: mapId, isCcpId: 1}, {dialogElement: dialogElement})
|
||||
.then(payload => updateDialog(payload.context.dialogElement, payload.data))
|
||||
.catch(payload => updateDialog(payload.context.dialogElement));
|
||||
};
|
||||
|
||||
// format system status for form select -----------------------------------------------------------------------
|
||||
// "default" selection (id = 0) prevents status from being overwritten
|
||||
// -> e.g. keep status information if system was just inactive (active = 0)
|
||||
let statusData = [{id: 0, text: 'auto'}];
|
||||
|
||||
// get current map data ---------------------------------------------------------------------------------------
|
||||
let mapData = mapContainer.getMapDataFromClient(['hasId']);
|
||||
let mapSystems = mapData.data.systems;
|
||||
let mapSystemCount = mapSystems.length;
|
||||
let mapTypeName = mapContainer.data('typeName');
|
||||
let maxAllowedSystems = Init.mapTypes[mapTypeName].defaultConfig.max_systems;
|
||||
|
||||
// show error if system max count reached ---------------------------------------------------------------------
|
||||
if(mapSystemCount >= maxAllowedSystems){
|
||||
Util.showNotify({title: 'Max system count exceeded', text: 'Limit of ' + maxAllowedSystems + ' systems reached', type: 'warning'});
|
||||
return;
|
||||
}
|
||||
|
||||
// disable systems that are already on it ---------------------------------------------------------------------
|
||||
let mapSystemIds = mapSystems.map(systemData => systemData.systemId);
|
||||
|
||||
// dialog data ------------------------------------------------------------------------------------------------
|
||||
let data = {
|
||||
id: config.dialogSystemId,
|
||||
select2Class: Util.config.select2Class,
|
||||
systemSelectClass: config.dialogSystemSelectClass,
|
||||
statusSelectId: config.dialogSystemStatusSelectId,
|
||||
lockId: config.dialogSystemLockId,
|
||||
rallyId: config.dialogSystemRallyId,
|
||||
|
||||
sectionInfoId: config.dialogSystemSectionInfoId,
|
||||
sectionInfoStatusId: config.dialogSystemSectionInfoStatusId,
|
||||
aliasId: config.dialogSystemAliasId,
|
||||
descriptionId: config.dialogSystemDescriptionId,
|
||||
createdId: config.dialogSystemCreatedId,
|
||||
updatedId: config.dialogSystemUpdatedId,
|
||||
statusData: statusData
|
||||
};
|
||||
|
||||
// set current position as "default" system to add ------------------------------------------------------------
|
||||
let currentCharacterLog = Util.getCurrentCharacterLog();
|
||||
|
||||
if(
|
||||
currentCharacterLog !== false &&
|
||||
mapSystemIds.indexOf( currentCharacterLog.system.id ) === -1
|
||||
){
|
||||
// current system is NOT already on this map
|
||||
// set current position as "default" system to add
|
||||
data.currentSystem = currentCharacterLog.system;
|
||||
}
|
||||
|
||||
requirejs(['text!templates/dialog/system.html', 'mustache'], (template, Mustache) => {
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let systemDialog = bootbox.dialog({
|
||||
title: 'Add new system',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-check"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function(e){
|
||||
// get form Values
|
||||
let form = this.find('form');
|
||||
|
||||
let formData = $(form).getFormValues();
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check whether the form is valid
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
// don't close dialog on invalid data
|
||||
if(formValid === false) return false;
|
||||
|
||||
// calculate new system position ----------------------------------------------------------
|
||||
let newPosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
// add new position
|
||||
let sourceSystem = null;
|
||||
if(options.sourceSystem !== undefined){
|
||||
sourceSystem = options.sourceSystem;
|
||||
|
||||
// get new position
|
||||
newPosition = calculateNewSystemPosition(sourceSystem);
|
||||
}else{
|
||||
// check mouse cursor position (add system to map)
|
||||
newPosition = {
|
||||
x: options.position.x,
|
||||
y: options.position.y
|
||||
};
|
||||
}
|
||||
|
||||
formData.position = newPosition;
|
||||
formData.mapId = mapId;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
this.find('.modal-content').showLoadingAnimation();
|
||||
|
||||
Util.request('PUT', 'system', [], formData, {
|
||||
systemDialog: systemDialog,
|
||||
formElement: form,
|
||||
map: map,
|
||||
sourceSystem: sourceSystem
|
||||
}, context => {
|
||||
// always do
|
||||
context.systemDialog.find('.modal-content').hideLoadingAnimation();
|
||||
}).then(
|
||||
payload => {
|
||||
Util.showNotify({title: 'New system', text: payload.data.name, type: 'success'});
|
||||
|
||||
callback(payload.context.map, payload.data, payload.context.sourceSystem);
|
||||
bootbox.hideAll();
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
systemDialog.on('show.bs.modal', function(e){
|
||||
let dialogElement = $(this);
|
||||
|
||||
// init "status" select2 ------------------------------------------------------------------------------
|
||||
for(let [statusName, data] of Object.entries(Init.systemStatus)){
|
||||
statusData.push({id: data.id, text: data.label, class: data.class});
|
||||
}
|
||||
|
||||
dialogElement.find('#' + config.dialogSystemStatusSelectId).initStatusSelect({
|
||||
data: statusData,
|
||||
iconClass: 'fa-tag'
|
||||
});
|
||||
|
||||
// initial dialog update with persistent system data --------------------------------------------------
|
||||
// -> only if system is preselected (e.g. current active system)
|
||||
let systemId = parseInt(dialogElement.find('.' + config.dialogSystemSelectClass).val()) || 0;
|
||||
if(systemId){
|
||||
requestSystemData(dialogElement, mapId, systemId);
|
||||
}
|
||||
});
|
||||
|
||||
systemDialog.on('shown.bs.modal', function(e){
|
||||
let dialogElement = $(this);
|
||||
|
||||
// no system selected
|
||||
updateDialog(dialogElement, false);
|
||||
|
||||
dialogElement.initTooltips();
|
||||
|
||||
// init system select live search - some delay until modal transition has finished
|
||||
let selectElement = dialogElement.find('.' + config.dialogSystemSelectClass);
|
||||
selectElement.delay(240).initSystemSelect({
|
||||
key: 'id',
|
||||
disabledOptions: mapSystemIds,
|
||||
onChange: systemId => {
|
||||
// on system select -> update dialog with persistent system data
|
||||
if(systemId){
|
||||
requestSystemData(dialogElement, mapId, systemId);
|
||||
}else{
|
||||
// no system selected
|
||||
updateDialog(dialogElement, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// show dialog
|
||||
systemDialog.modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show "set rally point" dialog for system
|
||||
* @param system
|
||||
*/
|
||||
$.fn.showRallyPointDialog = (system) => {
|
||||
let mapId = system.data('mapid');
|
||||
let systemId = system.data('id');
|
||||
let mapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
requirejs(['text!templates/dialog/system_rally.html', 'mustache'], function(template, Mustache){
|
||||
|
||||
let setCheckboxObserver = (checkboxes) => {
|
||||
checkboxes.each(function(){
|
||||
$(this).on('change', function(){
|
||||
// check all others
|
||||
let allUnchecked = true;
|
||||
checkboxes.each(function(){
|
||||
if(this.checked){
|
||||
allUnchecked = false;
|
||||
}
|
||||
});
|
||||
let textareaElement = $('#' + config.dialogRallyMessageId);
|
||||
if(allUnchecked){
|
||||
textareaElement.prop('disabled', true);
|
||||
}else{
|
||||
textareaElement.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
let sendPoke = (requestData, context) => {
|
||||
// lock dialog
|
||||
let dialogContent = context.rallyDialog.find('.modal-content');
|
||||
dialogContent.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.pokeRally,
|
||||
data: requestData,
|
||||
dataType: 'json',
|
||||
context: context
|
||||
}).done(function(data){
|
||||
|
||||
}).fail(function(jqXHR, status, error){
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': sendPoke', text: reason, type: 'warning'});
|
||||
}).always(function(){
|
||||
this.rallyDialog.find('.modal-content').hideLoadingAnimation();
|
||||
});
|
||||
};
|
||||
|
||||
let data = {
|
||||
id: config.dialogRallyId,
|
||||
|
||||
dialogRallyPokeDesktopId: config.dialogRallyPokeDesktopId,
|
||||
dialogRallyPokeSlackId: config.dialogRallyPokeSlackId,
|
||||
dialogRallyPokeDiscordId: config.dialogRallyPokeDiscordId,
|
||||
dialogRallyPokeMailId: config.dialogRallyPokeMailId,
|
||||
dialogRallyMessageId: config.dialogRallyMessageId ,
|
||||
|
||||
desktopRallyEnabled: true,
|
||||
slackRallyEnabled: Boolean(Util.getObjVal(mapData, 'config.logging.slackRally')),
|
||||
discordRallyEnabled: Boolean(Util.getObjVal(mapData, 'config.logging.discordRally')),
|
||||
mailRallyEnabled: Boolean(Util.getObjVal(mapData, 'config.logging.mailRally')),
|
||||
dialogRallyMessageDefault: config.dialogRallyMessageDefault,
|
||||
|
||||
systemUrl: MapUtil.getMapDeeplinkUrl(mapId, systemId),
|
||||
systemId: systemId
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let rallyDialog = bootbox.dialog({
|
||||
message: content,
|
||||
title: 'Set rally point in "' + system.getSystemInfo( ['alias'] ) + '"',
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-fw fa-volume-up"></i> set rally point',
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
let form = $('#' + config.dialogRallyId).find('form');
|
||||
// get form data
|
||||
let formData = form.getFormValues();
|
||||
|
||||
// update map
|
||||
system.setSystemRally(1, {
|
||||
poke: Boolean(formData.pokeDesktop)
|
||||
});
|
||||
system.markAsChanged();
|
||||
|
||||
// send poke data to server
|
||||
sendPoke(formData, {
|
||||
rallyDialog: this
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rallyDialog.initTooltips();
|
||||
|
||||
// after modal is shown ==================================================================================
|
||||
rallyDialog.on('shown.bs.modal', function(e){
|
||||
// set event for checkboxes
|
||||
setCheckboxObserver(rallyDialog.find(':checkbox'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* shows delete dialog for systems that should be deleted
|
||||
* @param map
|
||||
* @param systems
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.showDeleteSystemDialog = (map, systems = []) => {
|
||||
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);
|
||||
if(
|
||||
systemElement.data('mapid') === mapContainer.data('id') &&
|
||||
!systemElement.data('locked')
|
||||
){
|
||||
// system belongs to map -> valid system
|
||||
validDeleteSystems.push(system);
|
||||
|
||||
activeCharacters += (systemElement.data('userCount') ? parseInt( systemElement.data('userCount') ) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(validDeleteSystems.length){
|
||||
let msg = '';
|
||||
if(validDeleteSystems.length === 1){
|
||||
let deleteSystem = $(validDeleteSystems[0]);
|
||||
let systemName = deleteSystem.data('name');
|
||||
let systemAlias = deleteSystem.getSystemInfo( ['alias'] );
|
||||
|
||||
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{
|
||||
msg = 'Delete ' + validDeleteSystems.length + ' selected systems and their connections?';
|
||||
}
|
||||
|
||||
// add warning for active characters
|
||||
if(activeCharacters > 0){
|
||||
msg += ' <span class="txt-color txt-color-warning">Warning: ' + activeCharacters + ' active characters</span>';
|
||||
}
|
||||
|
||||
let systemDeleteDialog = bootbox.confirm(msg, result => {
|
||||
if(result){
|
||||
deleteSystems(map, validDeleteSystems, (deletedSystems) => {
|
||||
// callback function after deleted -> close dialog
|
||||
systemDeleteDialog.modal('hide');
|
||||
|
||||
// check whether all systems were deleted properly
|
||||
if(deletedSystems.length !== validDeleteSystems.length){
|
||||
let notDeletedCount = validDeleteSystems.length - deletedSystems.length;
|
||||
|
||||
Util.showNotify({
|
||||
title: 'Failed to delete systems',
|
||||
text: '(' + notDeletedCount + '/' + validDeleteSystems.length + ') systems could not be deleted',
|
||||
type: 'warning'}
|
||||
);
|
||||
}else if(deletedSystems.length === 1){
|
||||
Util.showNotify({title: 'System deleted', text: $(deletedSystems[0]).data('name'), type: 'success'});
|
||||
}else{
|
||||
Util.showNotify({title: systems.length + ' systems deleted', type: 'success'});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
Util.showNotify({title: 'No systems selected', type: 'warning'});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* toggle system tooltip (current pilot count)
|
||||
* @param show
|
||||
* @param tooltipOptions
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.toggleSystemTooltip = function(show, tooltipOptions){
|
||||
let highlightData = {
|
||||
good: {
|
||||
colorClass: 'txt-color-green',
|
||||
iconClass: 'fa-caret-up'
|
||||
},
|
||||
bad: {
|
||||
colorClass: 'txt-color-red',
|
||||
iconClass: 'fa-caret-down'
|
||||
}
|
||||
};
|
||||
|
||||
let getHighlightClass = (highlight) => {
|
||||
return Util.getObjVal(highlightData, highlight + '.colorClass') || '';
|
||||
};
|
||||
|
||||
let getHighlightIcon = (highlight) => {
|
||||
return Util.getObjVal(highlightData, highlight + '.iconClass') || '';
|
||||
};
|
||||
|
||||
let getTitle = (userCounter, highlight) => {
|
||||
return '<i class="fas ' + getHighlightIcon(highlight) + '"></i> ' + userCounter + '';
|
||||
};
|
||||
|
||||
return this.each(function(){
|
||||
let system = $(this);
|
||||
switch(show){
|
||||
case 'destroy':
|
||||
//destroy tooltip and remove some attributes which are not deleted by 'destroy'
|
||||
system.tooltip('destroy').removeAttr('title data-original-title');
|
||||
break;
|
||||
case 'hide':
|
||||
system.tooltip('hide');
|
||||
break;
|
||||
case 'show':
|
||||
// initial "show" OR "update" open tooltip
|
||||
// -> do not update tooltips while a system is dragged
|
||||
let showTooltip = !system.hasClass('jsPlumb_dragged');
|
||||
|
||||
if(system.data('bs.tooltip')){
|
||||
// tooltip initialized but could be hidden
|
||||
// check for title update
|
||||
if(
|
||||
tooltipOptions.hasOwnProperty('userCount') &&
|
||||
tooltipOptions.hasOwnProperty('highlight')
|
||||
){
|
||||
let currentTitle = system.attr('data-original-title');
|
||||
let newTitle = getTitle(tooltipOptions.userCount, tooltipOptions.highlight);
|
||||
|
||||
if(currentTitle !== newTitle){
|
||||
// update tooltip
|
||||
let tooltipInner = system.attr('title', newTitle).tooltip('fixTitle').data('bs.tooltip').$tip.find('.tooltip-inner');
|
||||
tooltipInner.html(newTitle);
|
||||
|
||||
// change highlight class
|
||||
let highlightClass = getHighlightClass(tooltipOptions.highlight);
|
||||
if( !tooltipInner.hasClass(highlightClass) ){
|
||||
tooltipInner.removeClass( getHighlightClass('good') + ' ' + getHighlightClass('bad')).addClass(highlightClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tip = system.data('bs.tooltip').tip();
|
||||
if( !tip.hasClass('in') && showTooltip){
|
||||
// update tooltip placement based on system position
|
||||
system.data('bs.tooltip').options.placement = getSystemTooltipPlacement(system);
|
||||
|
||||
system.tooltip('show');
|
||||
}
|
||||
}else{
|
||||
// no tooltip initialized
|
||||
// "some" config data is required
|
||||
if(
|
||||
tooltipOptions.hasOwnProperty('systemId') &&
|
||||
tooltipOptions.hasOwnProperty('userCount') &&
|
||||
tooltipOptions.hasOwnProperty('highlight')
|
||||
){
|
||||
let innerTooltipId = config.systemTooltipInnerIdPrefix + tooltipOptions.systemId;
|
||||
|
||||
let template = '<div class="tooltip" role="tooltip">' +
|
||||
'<div class="tooltip-arrow"></div>' +
|
||||
'<div id="' + innerTooltipId + '" class="tooltip-inner txt-color ' + config.systemTooltipInnerClass + '"></div>' +
|
||||
'</div>';
|
||||
|
||||
let options = {
|
||||
trigger: 'manual',
|
||||
placement: getSystemTooltipPlacement(system),
|
||||
html: true,
|
||||
animation: true,
|
||||
template: template,
|
||||
viewport: system.closest('.' + config.mapClass)
|
||||
};
|
||||
|
||||
// init new tooltip -> Do not show automatic maybe system is currently dragged
|
||||
system.attr('title', getTitle(tooltipOptions.userCount, tooltipOptions.highlight));
|
||||
system.tooltip(options);
|
||||
|
||||
system.one('shown.bs.tooltip', function(){
|
||||
// set highlight only on FIRST show
|
||||
$('#' + this.innerTooltipId).addClass(this.highlightClass);
|
||||
}.bind({
|
||||
highlightClass: getHighlightClass(tooltipOptions.highlight),
|
||||
innerTooltipId: innerTooltipId
|
||||
}));
|
||||
|
||||
if(showTooltip){
|
||||
system.tooltip('show');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get tooltip position (top, bottom) based on system position
|
||||
* @param system
|
||||
* @returns {string}
|
||||
*/
|
||||
let getSystemTooltipPlacement = (system) => {
|
||||
let offsetParent = system.parent().offset();
|
||||
let offsetSystem = system.offset();
|
||||
|
||||
return (offsetSystem.top - offsetParent.top < 27) ? 'bottom' : 'top';
|
||||
};
|
||||
|
||||
/**
|
||||
* delete system(s) with all their connections
|
||||
* (ajax call) remove system from DB
|
||||
* @param map
|
||||
* @param systems
|
||||
* @param callback function
|
||||
*/
|
||||
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
|
||||
let mapContainer = $( map.getContainer() );
|
||||
let systemIds = systems.map(system => $(system).data('id'));
|
||||
|
||||
Util.request('DELETE', 'system', systemIds, {
|
||||
mapId: mapContainer.data('id')
|
||||
}, {
|
||||
map: map,
|
||||
systems: systems
|
||||
}).then(
|
||||
payload => {
|
||||
// check if all systems were deleted that should get deleted
|
||||
let deletedSystems = payload.context.systems.filter(
|
||||
function(system){
|
||||
return this.indexOf( $(system).data('id') ) !== -1;
|
||||
}, payload.data
|
||||
);
|
||||
|
||||
// remove systems from map
|
||||
removeSystems(payload.context.map, deletedSystems);
|
||||
|
||||
callback(deletedSystems);
|
||||
},
|
||||
Util.handleAjaxErrorResponse
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* remove system(s) from map (no backend requests)
|
||||
* @param map
|
||||
* @param systems
|
||||
*/
|
||||
let removeSystems = (map, systems) => {
|
||||
let removeSystemCallback = deleteSystem => {
|
||||
map.remove(deleteSystem);
|
||||
};
|
||||
|
||||
for(let system of systems){
|
||||
system = $(system);
|
||||
|
||||
// check if system is "active"
|
||||
if(system.hasClass(config.systemActiveClass)){
|
||||
delete Init.currentSystemData;
|
||||
// get parent Tab Content and fire clear modules event
|
||||
let tabContentElement = MapUtil.getTabContentElementByMapElement(system);
|
||||
$(tabContentElement).trigger('pf:removeSystemModules');
|
||||
}
|
||||
|
||||
// remove endpoints and their connections
|
||||
// do not fire a "connectionDetached" event
|
||||
map.detachAllConnections(system, {fireEvent: false});
|
||||
|
||||
// destroy tooltip/popover
|
||||
system.toggleSystemTooltip('destroy', {});
|
||||
system.destroyPopover(true);
|
||||
|
||||
// remove system
|
||||
system.velocity('transition.whirlOut', {
|
||||
duration: Init.animationSpeed.mapDeleteSystem,
|
||||
complete: removeSystemCallback
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate the x/y coordinates for a new system - relativ to a source system
|
||||
* @param sourceSystem
|
||||
* @returns {{x: *, y: *}}
|
||||
*/
|
||||
let calculateNewSystemPosition = sourceSystem => {
|
||||
let mapContainer = sourceSystem.parent();
|
||||
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
|
||||
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
let positionFinder = new Layout.Position({
|
||||
container: mapContainer[0],
|
||||
center: sourceSystem[0],
|
||||
loops: 4,
|
||||
grid: mapContainer.hasClass(MapUtil.config.mapGridClass) ? grid : false,
|
||||
debug: false
|
||||
});
|
||||
|
||||
let dimensions = positionFinder.findNonOverlappingDimensions(1, 16);
|
||||
if(dimensions.length){
|
||||
//... empty map space found
|
||||
x = dimensions[0].left;
|
||||
y = dimensions[0].top;
|
||||
}else{
|
||||
//... fallback
|
||||
// related system is available
|
||||
let currentX = sourceSystem.css('left');
|
||||
let currentY = sourceSystem.css('top');
|
||||
|
||||
// remove "px"
|
||||
currentX = parseInt( currentX.substring(0, currentX.length - 2) );
|
||||
currentY = parseInt( currentY.substring(0, currentY.length - 2) );
|
||||
x = currentX + config.newSystemOffset.x;
|
||||
y = currentY + config.newSystemOffset.y;
|
||||
}
|
||||
|
||||
let newPosition = {
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
|
||||
return newPosition;
|
||||
};
|
||||
|
||||
/**
|
||||
* get new dom element for systemData that shows "info" data (additional data)
|
||||
* -> this is show below the system base data on map
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
let getHeadInfoElement = (data) => {
|
||||
let headInfo = null;
|
||||
let headInfoLeft = [];
|
||||
let headInfoRight = [];
|
||||
|
||||
if(data.shattered){
|
||||
headInfoLeft.push('<i class="fas fa-fw fa-skull ' + Util.getSecurityClassForSystem('SH') + '" title="shattered"></i>');
|
||||
}
|
||||
|
||||
// check systemData if headInfo element is needed
|
||||
if(data.statics && data.statics.length){
|
||||
// format wh statics
|
||||
for(let wormholeName of data.statics){
|
||||
let staticData = Object.assign({}, Init.wormholes[wormholeName]);
|
||||
headInfoRight.push(
|
||||
'<span class="' +
|
||||
Util.getSecurityClassForSystem(staticData.security) + ' ' +
|
||||
Util.config.popoverTriggerClass + '" data-name="' + staticData.name +
|
||||
'">' + staticData.security + '</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(headInfoLeft.length || headInfoRight.length){
|
||||
headInfo = $('<div>', {
|
||||
class: config.systemHeadInfoClass
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: config.systemHeadInfoLeftClass,
|
||||
html: headInfoLeft.join(' ')
|
||||
}),
|
||||
$('<div>', {
|
||||
class: config.systemHeadInfoRightClass,
|
||||
html: headInfoRight.join(' ')
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return headInfo;
|
||||
};
|
||||
|
||||
return {
|
||||
showNewSystemDialog: showNewSystemDialog,
|
||||
deleteSystems: deleteSystems,
|
||||
removeSystems: removeSystems,
|
||||
getHeadInfoElement: getHeadInfoElement
|
||||
};
|
||||
});
|
||||
1852
public/js/v1.5.2/app/map/util.js
Normal file
1852
public/js/v1.5.2/app/map/util.js
Normal file
File diff suppressed because it is too large
Load Diff
127
public/js/v1.5.2/app/map/worker.js
Normal file
127
public/js/v1.5.2/app/map/worker.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* 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 {
|
||||
getWebSocketURL: getWebSocketURL,
|
||||
init: init,
|
||||
send: send
|
||||
};
|
||||
});
|
||||
556
public/js/v1.5.2/app/mappage.js
Normal file
556
public/js/v1.5.2/app/mappage.js
Normal file
@@ -0,0 +1,556 @@
|
||||
/**
|
||||
* Main map application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'app/logging',
|
||||
'app/page',
|
||||
'app/map/worker',
|
||||
'app/module_map',
|
||||
'app/key',
|
||||
'app/ui/form_element'
|
||||
], ($, Init, Util, Render, Logging, Page, MapWorker, ModuleMap) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* main init "map" page
|
||||
*/
|
||||
$(() => {
|
||||
Util.initPrototypes();
|
||||
|
||||
// clear sessionStorage
|
||||
//Util.clearSessionStorage();
|
||||
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// set default select2 config
|
||||
Util.initDefaultSelect2Config();
|
||||
|
||||
// set default xEditable config
|
||||
Util.initDefaultEditableConfig();
|
||||
|
||||
// load page
|
||||
$('body').loadPageStructure().setGlobalShortcuts();
|
||||
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// init logging
|
||||
Logging.init();
|
||||
|
||||
let mapModule = $('#' + Util.config.mapModuleId);
|
||||
|
||||
// main update intervals/trigger (heartbeat)
|
||||
let updateTimeouts = {
|
||||
mapUpdate: 0,
|
||||
userUpdate: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* clear both main update timeouts
|
||||
* -> stop program from working -> shutdown
|
||||
*/
|
||||
let clearUpdateTimeouts = () => {
|
||||
for(let intervalKey in updateTimeouts){
|
||||
if(updateTimeouts.hasOwnProperty(intervalKey)){
|
||||
clearTimeout(updateTimeouts[intervalKey]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ajax error response handler function for main-ping functions
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
let handleAjaxErrorResponse = (jqXHR, status, error) => {
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
let errorData = [];
|
||||
let redirect = false; // redirect user to other page e.g. login
|
||||
let reload = true; // reload current page (default: true)
|
||||
|
||||
if(jqXHR.responseJSON){
|
||||
// handle JSON
|
||||
let responseObj = jqXHR.responseJSON;
|
||||
if(
|
||||
responseObj.error &&
|
||||
responseObj.error.length > 0
|
||||
){
|
||||
errorData = responseObj.error;
|
||||
}
|
||||
|
||||
if(responseObj.reroute){
|
||||
redirect = responseObj.reroute;
|
||||
}
|
||||
}else{
|
||||
// handle HTML
|
||||
errorData.push({
|
||||
type: 'error',
|
||||
message: 'Please restart and reload this page'
|
||||
});
|
||||
}
|
||||
|
||||
console.error(' ↪ %s Error response: %o', jqXHR.url, errorData);
|
||||
$(document).trigger('pf:shutdown', {
|
||||
status: jqXHR.status,
|
||||
reason: reason,
|
||||
error: errorData,
|
||||
redirect: redirect,
|
||||
reload: reload
|
||||
});
|
||||
};
|
||||
|
||||
// map init functions =========================================================================================
|
||||
|
||||
/**
|
||||
* get static init data and store response
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let initData = () => {
|
||||
|
||||
let initDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.initData).done(response => {
|
||||
if( response.error.length > 0 ){
|
||||
for(let i = 0; i < response.error.length; i++){
|
||||
Util.showNotify({
|
||||
title: response.error[i].title,
|
||||
text: response.error[i].message,
|
||||
type: response.error[i].type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Init.timer = response.timer;
|
||||
Init.mapTypes = response.mapTypes;
|
||||
Init.mapScopes = response.mapScopes;
|
||||
Init.connectionScopes = response.connectionScopes;
|
||||
Init.systemStatus = response.systemStatus;
|
||||
Init.systemType = response.systemType;
|
||||
Init.wormholes = response.wormholes;
|
||||
Init.characterStatus = response.characterStatus;
|
||||
Init.routes = response.routes;
|
||||
Init.url = response.url;
|
||||
Init.character = response.character;
|
||||
Init.slack = response.slack;
|
||||
Init.discord = response.discord;
|
||||
Init.structureStatus = response.structureStatus;
|
||||
Init.universeCategories = response.universeCategories;
|
||||
Init.routeSearch = response.routeSearch;
|
||||
|
||||
resolve({
|
||||
action: 'initData',
|
||||
data: false
|
||||
});
|
||||
}).fail((jqXHR, status, error) => {
|
||||
reject({
|
||||
action: 'shutdown',
|
||||
data: {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(initDataExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* get mapAccess Data for WebSocket subscription
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let getMapAccessData = () => {
|
||||
|
||||
let getMapAccessDataExecutor = (resolve, reject) => {
|
||||
$.getJSON(Init.path.getAccessData).done(response => {
|
||||
resolve({
|
||||
action: 'mapAccessData',
|
||||
data: response
|
||||
});
|
||||
}).fail((jqXHR, status, error) => {
|
||||
reject({
|
||||
action: 'shutdown',
|
||||
data: {
|
||||
jqXHR: jqXHR,
|
||||
status: status,
|
||||
error: error
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(getMapAccessDataExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* init main mapModule
|
||||
* -> initData() needs to be resolved first!
|
||||
* @param payload
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let initMapModule = (payload) => {
|
||||
|
||||
let initMapModuleExecutor = (resolve, reject) => {
|
||||
// init browser tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
|
||||
// init hidden context menu elements
|
||||
Page.renderMapContextMenus();
|
||||
|
||||
// init map module
|
||||
mapModule.initMapModule();
|
||||
|
||||
resolve({
|
||||
action: 'initMapModule',
|
||||
data: false
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(initMapModuleExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* request all map access data (tokens) -> required wor WebSocket subscription
|
||||
* -> initData() needs to be resolved first!
|
||||
* @param payloadMapAccessData
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let initMapWorker = (payloadMapAccessData) => {
|
||||
|
||||
let initMapWorkerExecutor = (resolve, reject) => {
|
||||
let getPayload = (command) => {
|
||||
return {
|
||||
action: 'initMapWorker',
|
||||
data: {
|
||||
syncStatus: Init.syncStatus.type,
|
||||
command: command
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let validMapAccessData = false;
|
||||
|
||||
if(payloadMapAccessData && payloadMapAccessData.action === 'mapAccessData'){
|
||||
let response = payloadMapAccessData.data;
|
||||
if(response.status === 'OK'){
|
||||
validMapAccessData = true;
|
||||
|
||||
// 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);
|
||||
|
||||
resolve(getPayload(MsgWorkerMessage.command));
|
||||
},
|
||||
onGet: (MsgWorkerMessage) => {
|
||||
switch(MsgWorkerMessage.task()){
|
||||
case 'mapUpdate':
|
||||
Util.updateCurrentMapData(MsgWorkerMessage.data());
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
case 'mapAccess':
|
||||
case 'mapDeleted':
|
||||
Util.deleteCurrentMapData(MsgWorkerMessage.data());
|
||||
ModuleMap.updateMapModule(mapModule);
|
||||
break;
|
||||
case 'mapSubscriptions':
|
||||
Util.updateCurrentMapUserData(MsgWorkerMessage.data());
|
||||
ModuleMap.updateActiveMapUserData(mapModule);
|
||||
break;
|
||||
}
|
||||
|
||||
Util.setSyncStatus('ws:get');
|
||||
},
|
||||
onClosed: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
reject(getPayload(MsgWorkerMessage.command));
|
||||
|
||||
},
|
||||
onError: (MsgWorkerMessage) => {
|
||||
Util.setSyncStatus(MsgWorkerMessage.command, MsgWorkerMessage.meta());
|
||||
reject(getPayload(MsgWorkerMessage.command));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if( !validMapAccessData ){
|
||||
reject(getPayload('Invalid mapAccessData'));
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(initMapWorkerExecutor);
|
||||
};
|
||||
|
||||
// run all init functions for mainModule and WebSocket configuration async
|
||||
Promise.all([initData(), getMapAccessData()])
|
||||
.then(payload => Promise.all([initMapModule(payload[0]), initMapWorker(payload[1])]))
|
||||
.then(payload => {
|
||||
// mapModule initialized and WebSocket configuration working
|
||||
console.ok('Client syncStatus: %s. %O resolved by command: %s!',
|
||||
payload[1].data.syncStatus,
|
||||
payload[1].action + '()',
|
||||
payload[1].data.command
|
||||
);
|
||||
})
|
||||
.catch(payload => {
|
||||
switch(payload.action){
|
||||
case 'shutdown':
|
||||
// ajax error
|
||||
handleAjaxErrorResponse(payload.data.jqXHR, payload.data.status, payload.data.error);
|
||||
break;
|
||||
case 'initMapWorker':
|
||||
// WebSocket not working -> no error here -> fallback to Ajax
|
||||
console.info('Client syncStatus: %s. %O rejected by command: %s! payload: %o',
|
||||
payload.data.syncStatus,
|
||||
payload.action + '()',
|
||||
payload.data.command,
|
||||
payload.data
|
||||
);
|
||||
break;
|
||||
default:
|
||||
console.error('Unhandled error thrown while initialization: %o ', payload);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* main function for init all map relevant trigger calls
|
||||
*/
|
||||
$.fn.initMapModule = function(){
|
||||
let mapModule = $(this);
|
||||
|
||||
// log keys -----------------------------------------------------------------------------------------------
|
||||
let logKeyServerMapData = Init.performanceLogging.keyServerMapData;
|
||||
let logKeyServerUserData = Init.performanceLogging.keyServerUserData;
|
||||
let locationToggle = $('#' + Util.config.headMapTrackingId);
|
||||
|
||||
// ping for main map update ===============================================================================
|
||||
/**
|
||||
* @param forceUpdateMapData // force request to be send
|
||||
*/
|
||||
let triggerMapUpdatePing = (forceUpdateMapData) => {
|
||||
|
||||
// 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: ModuleMap.getMapModuleDataForUpdate(mapModule),
|
||||
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(
|
||||
forceUpdateMapData ||
|
||||
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
|
||||
ModuleMap.updateMapModule(mapModule).then(() => {
|
||||
// map update done, init new trigger
|
||||
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let mapUpdateDelay = Util.getCurrentTriggerDelay(logKeyServerMapData, 0);
|
||||
|
||||
// init new trigger
|
||||
initMapUpdatePing(false);
|
||||
|
||||
// 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(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 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,
|
||||
getMapUserData: Util.getSyncType() === 'webSocket' ? 0 : 1,
|
||||
mapTracking: locationToggle.is(':checked') ? 1 : 0, // location tracking
|
||||
systemData: Util.getCurrentSystemData()
|
||||
};
|
||||
|
||||
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 &&
|
||||
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);
|
||||
|
||||
// update system info panels
|
||||
if(data.system){
|
||||
ModuleMap.updateSystemModulesData(mapModule, data.system);
|
||||
}
|
||||
|
||||
// store current map user data (cache)
|
||||
if(data.mapUserData !== undefined){
|
||||
Util.setCurrentMapUserData(data.mapUserData);
|
||||
}
|
||||
|
||||
// update map module character data
|
||||
ModuleMap.updateActiveMapUserData(mapModule).then(() => {
|
||||
// map module update done, init new trigger
|
||||
initMapUserUpdatePing();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* init (schedule) next MapUpdate Ping
|
||||
*/
|
||||
let initMapUpdatePing = (forceUpdateMapData) => {
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let delay = Util.getCurrentTriggerDelay(logKeyServerMapData, 0);
|
||||
|
||||
updateTimeouts.mapUpdate = setTimeout((forceUpdateMapData) => {
|
||||
triggerMapUpdatePing(forceUpdateMapData);
|
||||
}, delay, forceUpdateMapData);
|
||||
};
|
||||
|
||||
/**
|
||||
* init (schedule) next MapUserUpdate Ping
|
||||
*/
|
||||
let initMapUserUpdatePing = () => {
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
let delay = Util.getCurrentTriggerDelay(logKeyServerUserData, 0);
|
||||
|
||||
updateTimeouts.userUpdate = setTimeout(() => {
|
||||
triggerUserUpdatePing();
|
||||
}, delay);
|
||||
};
|
||||
|
||||
// initial start of the map update function
|
||||
triggerMapUpdatePing(true);
|
||||
|
||||
// Send map update request on tab close/reload, in order to save map changes that
|
||||
// haven´t been saved through default update trigger
|
||||
window.addEventListener('beforeunload', function(e){
|
||||
// save unsaved map changes ...
|
||||
triggerMapUpdatePing();
|
||||
|
||||
// check if character should be switched on reload or current character should be loaded afterwards
|
||||
let characterSwitch = Boolean( $('body').data('characterSwitch') );
|
||||
if(!characterSwitch){
|
||||
let characterId = Util.getCurrentCharacterId();
|
||||
if(characterId){
|
||||
Util.setCookie('old_char_id', characterId, 3, 's');
|
||||
}
|
||||
}
|
||||
|
||||
// IMPORTANT, return false in order to not "abort" ajax request in background!
|
||||
return false;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
1374
public/js/v1.5.2/app/module_map.js
Normal file
1374
public/js/v1.5.2/app/module_map.js
Normal file
File diff suppressed because it is too large
Load Diff
199
public/js/v1.5.2/app/notification.js
Normal file
199
public/js/v1.5.2/app/notification.js
Normal file
@@ -0,0 +1,199 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'pnotify',
|
||||
//'pnotify.buttons',
|
||||
//'pnotify.confirm',
|
||||
'pnotify.nonblock',
|
||||
'pnotify.desktop',
|
||||
//'pnotify.history',
|
||||
'pnotify.callbacks'
|
||||
], function($, Init, PNotify){
|
||||
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
title: '',
|
||||
text: '',
|
||||
type: '', // 'info', 'success', error, 'warning'
|
||||
icon: false,
|
||||
styling: 'fontawesome', // 'fontawesome', 'bootstrap3', 'jqueryui'
|
||||
animate_speed: 'fast', // animation speed for notifications moving up/down
|
||||
hide: true, // close after few seconds
|
||||
delay: 5000, // visible time for notification in browser
|
||||
mouse_reset: true, // Reset the hide timer if the mouse moves over the notice.
|
||||
shadow: true,
|
||||
addclass: 'stack-bottomright', // class for display, must changed on stack different stacks
|
||||
width: '250px',
|
||||
// nonblock extension parameter (click through notifications)
|
||||
nonblock: {
|
||||
nonblock: true, // change for enable
|
||||
nonblock_opacity: 0.9
|
||||
},
|
||||
// desktop extension "Web Notifications"
|
||||
desktop: {
|
||||
desktop: false, // change for enable
|
||||
icon: Init.path.img + 'notifications/logo.png' // default image for desktop notifications
|
||||
}
|
||||
};
|
||||
|
||||
// initial page title (cached)
|
||||
let initialPageTitle = document.title;
|
||||
|
||||
// global blink timeout cache
|
||||
let blinkTimer;
|
||||
|
||||
// stack container for all notifications
|
||||
let stack = {
|
||||
bottomRight: {
|
||||
stack: {
|
||||
dir1: 'up',
|
||||
dir2: 'left',
|
||||
firstpos1: 30,
|
||||
firstpos2: 10,
|
||||
spacing1: 5,
|
||||
spacing2: 5,
|
||||
push: 'bottom'
|
||||
},
|
||||
addclass: 'stack-bottomright',
|
||||
width: '250px',
|
||||
},
|
||||
barBottom: {
|
||||
stack: {
|
||||
dir1: 'up',
|
||||
dir2: 'right',
|
||||
// context: $('body'),
|
||||
spacing1: 0,
|
||||
spacing2: 0
|
||||
},
|
||||
addclass: 'stack-bar-bottom',
|
||||
width: '70%',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* show a notification in browser and/or "Web Notifications" in OS
|
||||
* @param customConfig
|
||||
* @param settings
|
||||
*/
|
||||
let showNotify = function(customConfig, settings){
|
||||
customConfig = $.extend(true, {}, config, customConfig );
|
||||
|
||||
// desktop notification
|
||||
if(
|
||||
settings &&
|
||||
settings.desktop === true
|
||||
){
|
||||
// ask for Web Notifications permission
|
||||
PNotify.desktop.permission();
|
||||
|
||||
customConfig.delay = 10000;
|
||||
customConfig.nonblock.nonblock = false; // true results in error on "click" desktop notification
|
||||
customConfig.desktop.desktop = true;
|
||||
|
||||
// make browser tab blink
|
||||
startTabBlink(customConfig.title);
|
||||
}
|
||||
|
||||
// set notification stack
|
||||
if(
|
||||
settings &&
|
||||
settings.stack
|
||||
){
|
||||
customConfig.stack = stack[settings.stack].stack;
|
||||
customConfig.addclass = stack[settings.stack].addclass;
|
||||
customConfig.width = stack[settings.stack].width;
|
||||
}else{
|
||||
customConfig.stack = stack.bottomRight.stack;
|
||||
customConfig.addclass = stack.bottomRight.addclass;
|
||||
}
|
||||
|
||||
switch(customConfig.type){
|
||||
case 'info':
|
||||
customConfig.icon = 'fas fa-info fa-fw fa-lg';
|
||||
break;
|
||||
case 'success':
|
||||
customConfig.icon = 'fas fa-check fa-fw fa-lg';
|
||||
break;
|
||||
case 'warning':
|
||||
customConfig.icon = 'fas fa-exclamation-triangle fa-fw fa-lg';
|
||||
break;
|
||||
case 'error':
|
||||
customConfig.icon = 'fas fa-times fa-fw fa-lg';
|
||||
break;
|
||||
case 'lock':
|
||||
customConfig.icon = 'fas fa-lock fa-fw fa-lg';
|
||||
customConfig.type = 'success';
|
||||
break;
|
||||
case 'unlock':
|
||||
customConfig.icon = 'fas fa-unlock fa-fw fa-lg';
|
||||
customConfig.type = 'info';
|
||||
break;
|
||||
default:
|
||||
customConfig.icon = false;
|
||||
}
|
||||
|
||||
let notify = new PNotify(customConfig);
|
||||
|
||||
if(
|
||||
settings &&
|
||||
settings.click
|
||||
){
|
||||
// set onclick for notification
|
||||
notify.get().on('click', settings.click);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* change document.title and make the browsers tab blink
|
||||
* @param blinkTitle
|
||||
*/
|
||||
let startTabBlink = function(blinkTitle){
|
||||
let initBlink = (function(blinkTitle){
|
||||
|
||||
// count blinks if tab is currently active
|
||||
let activeTabBlinkCount = 0;
|
||||
|
||||
let blink = function(){
|
||||
// number of "blinks" should be limited if tab is currently active
|
||||
if(window.isVisible){
|
||||
activeTabBlinkCount++;
|
||||
}
|
||||
|
||||
// toggle page title
|
||||
document.title = (document.title === blinkTitle) ? initialPageTitle : blinkTitle;
|
||||
|
||||
if(activeTabBlinkCount > 10){
|
||||
stopTabBlink();
|
||||
}
|
||||
};
|
||||
|
||||
return function(){
|
||||
if(!blinkTimer){
|
||||
blinkTimer = setInterval(blink, 1000);
|
||||
}
|
||||
};
|
||||
}( blinkTitle ));
|
||||
|
||||
initBlink();
|
||||
};
|
||||
|
||||
/**
|
||||
* stop blinking document.title
|
||||
*/
|
||||
let stopTabBlink = function(){
|
||||
if(blinkTimer){
|
||||
clearInterval(blinkTimer);
|
||||
document.title = initialPageTitle;
|
||||
blinkTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
showNotify: showNotify,
|
||||
startTabBlink: startTabBlink,
|
||||
stopTabBlink: stopTabBlink
|
||||
};
|
||||
});
|
||||
|
||||
1328
public/js/v1.5.2/app/page.js
Normal file
1328
public/js/v1.5.2/app/page.js
Normal file
File diff suppressed because it is too large
Load Diff
39
public/js/v1.5.2/app/promises/promise.deferred.js
Normal file
39
public/js/v1.5.2/app/promises/promise.deferred.js
Normal file
@@ -0,0 +1,39 @@
|
||||
define([], () => {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Deferred Promise implementation
|
||||
* @see https://stackoverflow.com/a/47112177/4329969
|
||||
*/
|
||||
return class DeferredPromise {
|
||||
|
||||
constructor(){
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
// assign the resolve and reject functions to `this`
|
||||
// making them usable on the class instance
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});
|
||||
|
||||
// bind `then` and `catch` to implement the same interface as Promise
|
||||
this.then = this._promise.then.bind(this._promise);
|
||||
this.catch = this._promise.catch.bind(this._promise);
|
||||
}
|
||||
|
||||
set data(data){
|
||||
if(data){
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
return this._data;
|
||||
}
|
||||
|
||||
get data(){
|
||||
return this._data;
|
||||
}
|
||||
|
||||
get [Symbol.toStringTag]() {
|
||||
return 'Promise';
|
||||
}
|
||||
};
|
||||
});
|
||||
69
public/js/v1.5.2/app/promises/promise.timeout.js
Normal file
69
public/js/v1.5.2/app/promises/promise.timeout.js
Normal file
@@ -0,0 +1,69 @@
|
||||
define([], () => {
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
Example1 callback -------------------------------------------------------------------------------------------------
|
||||
new TimeoutPromise((resolve, reject) => {
|
||||
request.get(options, (error, response, body) => {
|
||||
if (!error && response.statusCode === 200) {
|
||||
resolve(body);
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}, 2000).then(data => {
|
||||
console.info((Date.now() - start)/1000, '--data --> = ', data);
|
||||
}).catch(error => {
|
||||
console.info((Date.now() - start)/1000, '--error --> = ', error);
|
||||
});
|
||||
|
||||
Example2 DeferredPromise ------------------------------------------------------------------------------------------
|
||||
let deferredPromise = new DeferredPromise();
|
||||
|
||||
new TimeoutPromise(deferredPromise, 2000).then(data => {
|
||||
console.info((Date.now() - start)/1000, '--data --> = ', data);
|
||||
}).catch(error => {
|
||||
console.info((Date.now() - start)/1000, '--error --> = ', error);
|
||||
});
|
||||
|
||||
deferredPromise.resolve('OK');
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Timeout Promise implementation
|
||||
* -> wraps Promise into TimeoutPromise
|
||||
* -> rejects Promise after timeout
|
||||
*
|
||||
* Example1:
|
||||
*
|
||||
*/
|
||||
return class TimeoutPromise extends Promise {
|
||||
|
||||
constructor(callback, timeout = 6000){
|
||||
let timer;
|
||||
let promise = callback[Symbol.toStringTag] === 'Promise' ? callback : new Promise(callback);
|
||||
//let promise = new Promise(callback);
|
||||
|
||||
let wrapperPromise = Promise.race([
|
||||
promise,
|
||||
new Promise((resolve, reject) => {
|
||||
timer = setTimeout(timeout => {
|
||||
reject(new Error('Promise timeout after ' + timeout + 'ms'));
|
||||
}, timeout, timeout);
|
||||
}),
|
||||
]);
|
||||
|
||||
super(function(resolve, reject){
|
||||
wrapperPromise.then(data => {
|
||||
clearTimeout(timer);
|
||||
resolve(data);
|
||||
}).catch(error => {
|
||||
clearTimeout(timer);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
150
public/js/v1.5.2/app/render.js
Normal file
150
public/js/v1.5.2/app/render.js
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Render controller
|
||||
*/
|
||||
|
||||
define(['jquery', 'mustache'], ($, Mustache) => {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* render Mustache template
|
||||
* @param path
|
||||
* @param data
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
let render = (path, data) => {
|
||||
let renderExecutor = resolve => {
|
||||
requirejs(['text!templates/' + path + '.html'], template => {
|
||||
resolve(Mustache.render(template, data));
|
||||
});
|
||||
};
|
||||
return new Promise(renderExecutor);
|
||||
};
|
||||
|
||||
/**
|
||||
* convert JSON object into HTML highlighted string
|
||||
* @param obj
|
||||
*/
|
||||
let highlightJson = (obj) => {
|
||||
let multiplyString = (num, str) => {
|
||||
let sb = [];
|
||||
for(let i = 0; i < num; i++){
|
||||
sb.push(str);
|
||||
}
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
let dateObj = new Date();
|
||||
let regexpObj = new RegExp();
|
||||
let tab = multiplyString(1, ' ');
|
||||
let isCollapsible = true;
|
||||
let quoteKeys = false;
|
||||
let expImageClicked = '(() => {let container=this.parentNode.nextSibling; container.style.display=container.style.display===\'none\'?\'inline\':\'none\'})();';
|
||||
|
||||
let checkForArray = function(obj){
|
||||
return obj &&
|
||||
typeof obj === 'object' &&
|
||||
typeof obj.length === 'number' &&
|
||||
!(obj.propertyIsEnumerable('length'));
|
||||
};
|
||||
|
||||
let getRow = function(indent, data, isPropertyContent){
|
||||
let tabs = '';
|
||||
for(let i = 0; i < indent && !isPropertyContent; i++) tabs += tab;
|
||||
if(data !== null && data.length > 0 && data.charAt(data.length - 1) !== '\n')
|
||||
data = data + '\n';
|
||||
return tabs + data;
|
||||
};
|
||||
|
||||
let formatLiteral = function(literal, quote, comma, indent, isArray, style){
|
||||
if(typeof literal === 'string')
|
||||
literal = literal.split('<').join('<').split('>').join('>');
|
||||
let str = '<span class="' + style + '">' + quote + literal + quote + comma + '</span>';
|
||||
if(isArray) str = getRow(indent, str);
|
||||
return str;
|
||||
};
|
||||
|
||||
let formatFunction = function(indent, obj){
|
||||
let tabs = '';
|
||||
for(let i = 0; i < indent; i++) tabs += tab;
|
||||
let funcStrArray = obj.toString().split('\n');
|
||||
let str = '';
|
||||
for(let i = 0; i < funcStrArray.length; i++){
|
||||
str += ((i === 0) ? '' : tabs) + funcStrArray[i] + '\n';
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
let highlight = (obj, indent, addComma, isArray, isPropertyContent) => {
|
||||
let html = '';
|
||||
|
||||
let comma = (addComma) ? '<span class="pf-code-Comma">,</span> ' : '';
|
||||
let type = typeof obj;
|
||||
let clpsHtml = '';
|
||||
if(checkForArray(obj)){
|
||||
if(obj.length === 0){
|
||||
html += getRow(indent, '<span class="pf-code-ArrayBrace">[ ]</span>' + comma, isPropertyContent);
|
||||
}else{
|
||||
clpsHtml = isCollapsible ? '<span><i class="fas fa-fw fa-plus-square" onClick="' + expImageClicked + '"></i></span><span class="collapsible">' : '';
|
||||
html += getRow(indent, '<span class="pf-code-ArrayBrace">[</span>' + clpsHtml, isPropertyContent);
|
||||
for(let i = 0; i < obj.length; i++){
|
||||
html += highlight(obj[i], indent + 1, i < (obj.length - 1), true, false);
|
||||
}
|
||||
clpsHtml = isCollapsible ? '</span>' : '';
|
||||
html += getRow(indent, clpsHtml + '<span class="pf-code-ArrayBrace">]</span>' + comma);
|
||||
}
|
||||
}else if(type === 'object'){
|
||||
if(obj === null){
|
||||
html += formatLiteral('null', '', comma, indent, isArray, 'pf-code-Null');
|
||||
}else if(obj.constructor === dateObj.constructor){
|
||||
html += formatLiteral('new Date(' + obj.getTime() + ') /*' + obj.toLocaleString() + '*/', '', comma, indent, isArray, 'Date');
|
||||
}else if(obj.constructor === regexpObj.constructor){
|
||||
html += formatLiteral('new RegExp(' + obj + ')', '', comma, indent, isArray, 'RegExp');
|
||||
}else{
|
||||
let numProps = 0;
|
||||
for(let prop in obj) numProps++;
|
||||
if(numProps === 0){
|
||||
html += getRow(indent, '<span class="pf-code-ObjectBrace">{ }</span>' + comma, isPropertyContent);
|
||||
}else{
|
||||
clpsHtml = isCollapsible ? '<span><i class="fas fa-fw fa-plus-square" onClick="' + expImageClicked + '"></i></span><span class="collapsible">' : '';
|
||||
html += getRow(indent, '<span class="pf-code-ObjectBrace">{</span>' + clpsHtml, isPropertyContent);
|
||||
let j = 0;
|
||||
for(let prop in obj){
|
||||
if(obj.hasOwnProperty(prop)){
|
||||
let quote = quoteKeys ? '"' : '';
|
||||
html += getRow(indent + 1, '<span class="pf-code-PropertyName">' + quote + prop + quote + '</span>: ' + highlight(obj[prop], indent + 1, ++j < numProps, false, true));
|
||||
}
|
||||
}
|
||||
clpsHtml = isCollapsible ? '</span>' : '';
|
||||
html += getRow(indent, clpsHtml + '<span class="pf-code-ObjectBrace">}</span>' + comma);
|
||||
}
|
||||
}
|
||||
}else if(type === 'number'){
|
||||
html += formatLiteral(obj, '', comma, indent, isArray, 'pf-code-Number');
|
||||
}else if(type === 'boolean'){
|
||||
html += formatLiteral(obj, '', comma, indent, isArray, 'pf-code-Boolean');
|
||||
}else if(type === 'function'){
|
||||
if(obj.constructor === regexpObj.constructor){
|
||||
html += formatLiteral('new RegExp(' + obj + ')', '', comma, indent, isArray, 'RegExp');
|
||||
}else{
|
||||
obj = formatFunction(indent, obj);
|
||||
html += formatLiteral(obj, '', comma, indent, isArray, 'pf-code-Function');
|
||||
}
|
||||
}else if(type === 'undefined'){
|
||||
html += formatLiteral('undefined', '', comma, indent, isArray, 'pf-code-Null');
|
||||
}else{
|
||||
html += formatLiteral(obj.toString().split('\\').join('\\\\').split('"').join('\\"'), '"', comma, indent, isArray, 'pf-code-String');
|
||||
}
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
return highlight(obj, 0, false, false, false);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render,
|
||||
highlightJson: highlightJson
|
||||
};
|
||||
});
|
||||
295
public/js/v1.5.2/app/setup.js
Normal file
295
public/js/v1.5.2/app/setup.js
Normal file
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* Main setupPage application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/worker'
|
||||
], function($, Init, Util, MapWorker){
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
splashOverlayClass: 'pf-splash' // class for "splash" overlay
|
||||
};
|
||||
|
||||
/**
|
||||
* send ajax request for index build
|
||||
* @param url
|
||||
* @param requestData
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
let sendRequest = (url, requestData, context, callback) => {
|
||||
if(requestData.count === 0){
|
||||
// first iteration
|
||||
context.target.button('loading');
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: requestData,
|
||||
context: context
|
||||
}).done(function(data){
|
||||
callback(this, data);
|
||||
}).fail(function(jqXHR, status, error){
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': Failed. Please retry', text: reason, type: 'warning'});
|
||||
this.target.button('reset');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
let setPageObserver = () => {
|
||||
let body = $('body');
|
||||
|
||||
// navigation (scroll) ----------------------------------------------------------------------------------------
|
||||
Util.initPageScroll(body);
|
||||
|
||||
// collapse ---------------------------------------------------------------------------------------------------
|
||||
body.find('[data-toggle="collapse"]').css({cursor: 'pointer'}).on('click', function(){
|
||||
$(this).find('.pf-animate-rotate').toggleClass('right');
|
||||
});
|
||||
|
||||
// buttons ----------------------------------------------------------------------------------------------------
|
||||
// exclude "download" && "navigation" buttons
|
||||
body.find('.btn')
|
||||
.not('.navbar-fixed-bottom .btn')
|
||||
.not('[data-action="clearIndex"]')
|
||||
.not('[data-action="buildIndex"]')
|
||||
.not('[href^="?export"]').on('click', function(e){
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay();
|
||||
});
|
||||
|
||||
// build/clear index buttons ----------------------------------------------------------------------------------
|
||||
// clear index buttons ----------------------------------------------------------------------------------------
|
||||
body.find('.btn[data-action="buildIndex"], .btn[data-action="clearIndex"]').on('click', function(e){
|
||||
e.preventDefault();
|
||||
let element = $(this);
|
||||
let url = '/api/setup/' + element.attr('data-action');
|
||||
sendRequest(url, {
|
||||
type: element.attr('data-type'),
|
||||
count: 0,
|
||||
offset: 0
|
||||
}, {
|
||||
target: element,
|
||||
url: url
|
||||
}, updateIndexCount);
|
||||
});
|
||||
|
||||
// tooltips ---------------------------------------------------------------------------------------------------
|
||||
body.find('[title]').tooltip();
|
||||
|
||||
// change url (remove logout parameter)
|
||||
if(history.pushState){
|
||||
history.pushState({}, '', location.protocol + '//' + location.host + location.pathname);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* update data count label for "indexed data"
|
||||
* @param context
|
||||
* @param responseData
|
||||
*/
|
||||
let updateIndexCount = (context, responseData) => {
|
||||
let countElement = context.target.closest('.row').children().eq(1).find('kbd');
|
||||
countElement.text(responseData.countBuildAll + '/' + responseData.countAll);
|
||||
countElement.removeClass('txt-color-success txt-color-danger txt-color-warning');
|
||||
if(responseData.countBuildAll >=responseData.countAll){
|
||||
countElement.addClass('txt-color-success');
|
||||
}else if(responseData.countBuildAll > 0){
|
||||
countElement.addClass('txt-color-warning');
|
||||
}else{
|
||||
countElement.addClass('txt-color-danger');
|
||||
}
|
||||
|
||||
context.target.find('.btn-progress').html(' ' + responseData.progress + '%').css('width', responseData.progress + '%');
|
||||
|
||||
// send next chunk of rows -> import only
|
||||
if(
|
||||
context.target.attr('data-action') === 'buildIndex' &&
|
||||
responseData.countBuildAll < responseData.countAll
|
||||
){
|
||||
sendRequest(context.url, {
|
||||
type: responseData.type,
|
||||
count: responseData.count,
|
||||
offset: responseData.offset
|
||||
}, {
|
||||
target: context.target,
|
||||
url: context.url
|
||||
}, updateIndexCount);
|
||||
}else{
|
||||
context.target.button('reset');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* perform a basic check if Clients (browser) can connect to the webSocket server
|
||||
*/
|
||||
let testWebSocket = () => {
|
||||
let tcpSocketPanel = $('#pf-setup-tcpSocket');
|
||||
let webSocketPanel = $('#pf-setup-webSocket');
|
||||
let webSocketURI = MapWorker.getWebSocketURL();
|
||||
let sslIcon = webSocketURI.startsWith('wss:') ?
|
||||
'<i class="fas fa-fw fa-lock txt-color txt-color-success"></i>' :
|
||||
'<i class="fas fa-fw fa-unlock txt-color txt-color-warning"></i>';
|
||||
|
||||
webSocketPanel.showLoadingAnimation();
|
||||
|
||||
let removeColorClasses = (el) => {
|
||||
el.removeClass (function(index, css){
|
||||
return (css.match (/\btxt-color-\S+/g) || []).join(' ');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* updates the WebSocket panel with new data
|
||||
* @param data
|
||||
*/
|
||||
let updateWebSocketPanel = (data) => {
|
||||
let badgeSocketWarning = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-warning');
|
||||
let badgeSocketDanger = $('.navbar a[data-anchor="#pf-setup-socket"] .txt-color-danger');
|
||||
let socketWarningCount = parseInt(badgeSocketWarning.text()) || 0;
|
||||
let socketDangerCount = parseInt(badgeSocketDanger.text()) || 0;
|
||||
|
||||
if(data.uri){
|
||||
let uriRow = webSocketPanel.find('.panel-body table tr');
|
||||
uriRow.find('td:nth-child(2) kbd').html(data.uri.value);
|
||||
if(data.uri.status){
|
||||
let statusIcon = uriRow.find('td:nth-child(3) i');
|
||||
removeColorClasses(statusIcon);
|
||||
statusIcon.toggleClass('fa-exclamation-triangle', false).toggleClass('fa-check', true).addClass('txt-color-success');
|
||||
|
||||
// update head badge. "Decrease" warning count, default for "URI" connection is "warn + 1"
|
||||
socketWarningCount--;
|
||||
}
|
||||
}
|
||||
|
||||
if(data.status){
|
||||
let footer = webSocketPanel.find('.panel-footer h3');
|
||||
removeColorClasses(footer);
|
||||
footer.text(data.status.label).addClass(data.status.class);
|
||||
|
||||
// update head badge
|
||||
switch(data.status.type){
|
||||
case 'success':
|
||||
socketWarningCount = '';
|
||||
socketDangerCount = '';
|
||||
break;
|
||||
case 'warning':
|
||||
break;
|
||||
case 'danger':
|
||||
socketDangerCount = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
badgeSocketWarning.text(socketWarningCount ? socketWarningCount : '');
|
||||
badgeSocketDanger.text(socketDangerCount ? socketDangerCount : '');
|
||||
};
|
||||
|
||||
// update initial
|
||||
updateWebSocketPanel({
|
||||
uri: {
|
||||
value: sslIcon + ' ' + webSocketURI,
|
||||
status: true
|
||||
},
|
||||
status: {
|
||||
type: 'warning',
|
||||
label: 'CONNECTING…',
|
||||
class: 'txt-color-warning'
|
||||
}
|
||||
});
|
||||
|
||||
// try to connect to WebSocket server
|
||||
let socket = new WebSocket(webSocketURI);
|
||||
|
||||
socket.onopen = (e) => {
|
||||
updateWebSocketPanel({
|
||||
status: {
|
||||
type: 'warning',
|
||||
label: 'OPEN wait for response…',
|
||||
class: 'txt-color-warning'
|
||||
}
|
||||
});
|
||||
|
||||
// sent token and check response
|
||||
socket.send(JSON.stringify({
|
||||
task: 'healthCheck',
|
||||
load: tcpSocketPanel.data('token')
|
||||
}));
|
||||
|
||||
webSocketPanel.hideLoadingAnimation();
|
||||
};
|
||||
|
||||
socket.onmessage = (e) => {
|
||||
let response = JSON.parse(e.data);
|
||||
|
||||
if(response === 1){
|
||||
// SUCCESS
|
||||
updateWebSocketPanel({
|
||||
status: {
|
||||
type: 'success',
|
||||
label: 'CONNECTED',
|
||||
class: 'txt-color-success'
|
||||
}
|
||||
});
|
||||
}else{
|
||||
// Got response but INVALID
|
||||
updateWebSocketPanel({
|
||||
status: {
|
||||
type: 'warning',
|
||||
label: 'INVALID RESPONSE',
|
||||
class: 'txt-color-warning'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
socket.onerror = (e) => {
|
||||
updateWebSocketPanel({
|
||||
status: {
|
||||
type: 'danger',
|
||||
label: 'CONNECTION ERROR',
|
||||
class: 'txt-color-danger'
|
||||
}
|
||||
});
|
||||
|
||||
webSocketPanel.hideLoadingAnimation();
|
||||
};
|
||||
|
||||
socket.onclose = (closeEvent) => {
|
||||
updateWebSocketPanel({
|
||||
status: {
|
||||
type: 'danger',
|
||||
label: 'CONNECTION FAILED',
|
||||
class: 'txt-color-danger'
|
||||
}
|
||||
});
|
||||
|
||||
webSocketPanel.hideLoadingAnimation();
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* main init "setup" page
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
// show app information in browser console --------------------------------------------------------------------
|
||||
Util.showVersionInfo();
|
||||
|
||||
// hide splash loading animation ------------------------------------------------------------------------------
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
setPageObserver();
|
||||
|
||||
testWebSocket();
|
||||
});
|
||||
});
|
||||
187
public/js/v1.5.2/app/summernote.loader.js
Normal file
187
public/js/v1.5.2/app/summernote.loader.js
Normal file
@@ -0,0 +1,187 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'summernote'
|
||||
], ($, Init) => {
|
||||
'use strict';
|
||||
|
||||
// all Summernote stuff is available...
|
||||
let initDefaultSummernoteConfig = () => {
|
||||
// "length" hint plugin ---------------------------------------------------------------------------------------
|
||||
$.extend($.summernote.plugins, {
|
||||
/**
|
||||
* @param {Object} context - context object has status of editor.
|
||||
*/
|
||||
lengthField: function (context){
|
||||
let self = this;
|
||||
let ui = $.summernote.ui;
|
||||
|
||||
// add counter
|
||||
context.memo('button.lengthField', () => {
|
||||
return $('<kbd>', {
|
||||
class: ['text-right', 'txt-color'].join(' ')
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* update counter element with left chars
|
||||
* @param contents
|
||||
*/
|
||||
let updateCounter = (contents) => {
|
||||
let maxTextLength = context.options.maxTextLength;
|
||||
let textLength = contents.length;
|
||||
let counter = context.layoutInfo.toolbar.find('kbd');
|
||||
let counterLeft = maxTextLength - textLength;
|
||||
|
||||
counter.text(counterLeft).data('charCount', counterLeft);
|
||||
counter.toggleClass('txt-color-red', maxTextLength <= textLength);
|
||||
|
||||
// disable "save" button
|
||||
let saveBtn = context.layoutInfo.toolbar.find('.btn-save');
|
||||
saveBtn.prop('disabled', maxTextLength < textLength);
|
||||
};
|
||||
|
||||
// events
|
||||
this.events = {
|
||||
'summernote.init': function (we, e) {
|
||||
updateCounter(context.$note.summernote('code'));
|
||||
},
|
||||
'summernote.change': function(we, contents){
|
||||
updateCounter(contents);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// "discard" button plugin ------------------------------------------------------------------------------------
|
||||
$.extend($.summernote.plugins, {
|
||||
/**
|
||||
* @param {Object} context - context object has status of editor.
|
||||
*/
|
||||
discardBtn: function (context){
|
||||
let self = this;
|
||||
let ui = $.summernote.ui;
|
||||
|
||||
// add button
|
||||
context.memo('button.discardBtn', () => {
|
||||
let button = ui.button({
|
||||
contents: '<i class="fas fa-fw fa-ban"/>',
|
||||
container: 'body',
|
||||
click: function(){
|
||||
// show confirmation dialog
|
||||
$(this).confirmation('show');
|
||||
}
|
||||
});
|
||||
let $button = button.render();
|
||||
|
||||
// show "discard" changes confirmation
|
||||
let confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'top',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
title: 'discard changes',
|
||||
btnOkClass: 'btn btn-sm btn-warning',
|
||||
btnOkLabel: 'discard',
|
||||
btnOkIcon: 'fas fa-fw fa-ban',
|
||||
onConfirm: (e, target) => {
|
||||
// discard all changes
|
||||
context.$note.summernote('reset');
|
||||
context.$note.summernote('destroy');
|
||||
}
|
||||
};
|
||||
$button.confirmation(confirmationSettings);
|
||||
|
||||
return $button;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init new Summernote editor
|
||||
* @param element
|
||||
* @param options
|
||||
*/
|
||||
let initSummernote = (element, options) => {
|
||||
|
||||
let defaultOptions = {
|
||||
dialogsInBody: true,
|
||||
dialogsFade: true,
|
||||
//textareaAutoSync: false,
|
||||
//hintDirection: 'right',
|
||||
//tooltip: 'right',
|
||||
//container: 'body',
|
||||
styleTags: ['p', 'h2', 'h3', 'blockquote'],
|
||||
linkTargetBlank: true,
|
||||
tableClassName: 'table table-condensed table-bordered',
|
||||
insertTableMaxSize: {
|
||||
col: 5,
|
||||
row: 5
|
||||
},
|
||||
icons: {
|
||||
//'align': 'note-icon-align',
|
||||
'alignCenter': 'fas fa-align-center',
|
||||
'alignJustify': 'fas fa-align-justify',
|
||||
'alignLeft': 'fas fa-align-left',
|
||||
'alignRight': 'fas fa-align-right',
|
||||
//'rowBelow': 'note-icon-row-below',
|
||||
//'colBefore': 'note-icon-col-before',
|
||||
//'colAfter': 'note-icon-col-after',
|
||||
//'rowAbove': 'note-icon-row-above',
|
||||
//'rowRemove': 'note-icon-row-remove',
|
||||
//'colRemove': 'note-icon-col-remove',
|
||||
'indent': 'fas fa-indent',
|
||||
'outdent': 'fas fa-outdent',
|
||||
'arrowsAlt': 'fas fa-expand-arrows-alt',
|
||||
'bold': 'fas fa-bold',
|
||||
'caret': 'fas fa-caret-down',
|
||||
'circle': 'fas fa-circle',
|
||||
'close': 'fas fa-time',
|
||||
'code': 'fas fa-code',
|
||||
'eraser': 'fas fa-eraser',
|
||||
'font': 'fas fa-font',
|
||||
//'frame': 'note-icon-frame',
|
||||
'italic': 'fas fa-italic',
|
||||
'link': 'fas fa-link',
|
||||
'unlink': 'fas fa-unlink',
|
||||
'magic': 'fas fa-magic',
|
||||
'menuCheck': 'fas fa-check',
|
||||
'minus': 'fas fa-minus',
|
||||
'orderedlist': 'fas fa-list-ol',
|
||||
'pencil': 'fa-pen',
|
||||
'picture': 'fas fa-image',
|
||||
'question': 'fas fa-question',
|
||||
'redo': 'fas fa-redo',
|
||||
'square': 'fas fa-square',
|
||||
'strikethrough': 'fas fa-strikethrough',
|
||||
'subscript': 'fas fa-subscript',
|
||||
'superscript': 'fas fa-superscript',
|
||||
'table': 'fas fa-table',
|
||||
'textHeight': 'fas fa-text-height',
|
||||
'trash': 'fas fa-trash',
|
||||
'underline': 'fas fa-underline',
|
||||
'undo': 'fas fa-undo',
|
||||
'unorderedlist': 'fas fa-list-ul',
|
||||
'video': 'fab fa-youtube'
|
||||
},
|
||||
colors: [
|
||||
['#5cb85c', '#e28a0d', '#d9534f', '#e06fdf', '#9fa8da', '#e2ce48', '#428bca']
|
||||
],
|
||||
colorsName: [
|
||||
['Green', 'Orange', 'Red', 'Pink', 'Indigo', 'Yellow', 'Blue']
|
||||
],
|
||||
};
|
||||
|
||||
options = $.extend({}, defaultOptions, options);
|
||||
|
||||
element.summernote(options);
|
||||
};
|
||||
|
||||
initDefaultSummernoteConfig();
|
||||
|
||||
return {
|
||||
initSummernote: initSummernote
|
||||
};
|
||||
});
|
||||
314
public/js/v1.5.2/app/ui/demo_map.js
Normal file
314
public/js/v1.5.2/app/ui/demo_map.js
Normal file
@@ -0,0 +1,314 @@
|
||||
/**
|
||||
* Demo SVG map
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'lazylinepainter'
|
||||
], function($){
|
||||
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
headerSystemsContainerId: 'pf-header-systems', // id for systems layer
|
||||
headerSystemConnectorsId: 'pf-header-connectors', // id for connectors layer
|
||||
headerConnectionsContainerId: 'pf-header-connections', // id for connections layer
|
||||
headerBackgroundContainerId: 'pf-header-background', // id for background layer
|
||||
|
||||
headerSystemClass: 'pf-header-system', // class for all header background systems
|
||||
|
||||
// map dimensions
|
||||
mapWidth: 600, // map width (px)
|
||||
mapHeight: 380 // map height (px)
|
||||
};
|
||||
|
||||
/**
|
||||
* draw systems layer
|
||||
* @param callback
|
||||
*/
|
||||
let drawSystems = function(callback){
|
||||
|
||||
let pathObj = {
|
||||
systems: {
|
||||
strokepath: [
|
||||
// systems =======================================================================
|
||||
// 1
|
||||
{
|
||||
path: 'm 155 30 90 0 c 2.8 0 5 2.2 5 5 l 0 10 c 0 2.8 -2.2 5 -5 5 l -90 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -10 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#568A89' //teal
|
||||
},
|
||||
// 2
|
||||
{
|
||||
path: 'm 374 91 110 0 c 2.8 0 5 2.2 5 5 l 0 10 c 0 2.8 -2.2 5 -5 5 l -110 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -10 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#63676A' //gray
|
||||
},
|
||||
// 3
|
||||
{
|
||||
path: 'm 15 149 90 0 c 2.8 0 5 2.2 5 5 l 0 30 c 0 2.8 -2.2 5 -5 5 l -90 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -30 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#D9534F ' //red
|
||||
},
|
||||
// 4
|
||||
{
|
||||
path: 'm 235 230 90 0 c 2.8 0 5 2.2 5 5 l 0 10 c 0 2.8 -2.2 5 -5 5 l -90 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -10 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#63676A' //gray
|
||||
},
|
||||
// 5
|
||||
{
|
||||
path: 'm 175 330 90 0 c 2.8 0 5 2.2 5 5 l 0 30 c 0 2.8 -2.2 5 -5 5 l -90 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -30 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#E28A0D ' //orange
|
||||
},
|
||||
// 6
|
||||
{
|
||||
path: 'm 436 312 90 0 c 2.8 0 5 2.2 5 5 l 0 10 c 0 2.8 -2.2 5 -5 5 l -90 0 c -2.8 0 -5 -2.2 -5 -5 l 0 -10 c 0 -2.8 2.2 -5 5 -5 z',
|
||||
duration: 500,
|
||||
strokeColor: '#5CB85C ' //green
|
||||
}
|
||||
],
|
||||
dimensions: {
|
||||
width: config.mapWidth,
|
||||
height: config.mapHeight
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// draw systems into header
|
||||
$('#' + config.headerSystemsContainerId).lazylinepainter(
|
||||
{
|
||||
svgData: pathObj,
|
||||
strokeWidth: 2,
|
||||
strokeOpacity: 1,
|
||||
overrideKey: 'systems',
|
||||
strokeJoin: 'miter',
|
||||
strokeCap: 'butt',
|
||||
delay: 1000,
|
||||
onComplete: function(){
|
||||
drawConnectors(callback);
|
||||
}
|
||||
|
||||
}).lazylinepainter('paint');
|
||||
};
|
||||
|
||||
/**
|
||||
* draw connectors layer
|
||||
* @param callback
|
||||
*/
|
||||
let drawConnectors = function(callback){
|
||||
|
||||
let connectorDuration = 150;
|
||||
|
||||
let pathObj = {
|
||||
connectors: {
|
||||
strokepath: [
|
||||
// connectors ====================================================================
|
||||
// 1
|
||||
{
|
||||
path: 'm 250.4 34.8 c 1.7 0 3.1 1.3 3.9 2.9 0.8 1.7 0.8 3.7 0 5.3 -0.8 1.7 -2.4 2.7 -4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
{
|
||||
path: 'm 150 34.7 c -1.7 0 -3.1 1.3 -3.9 2.9 -0.8 1.7 -0.8 3.7 0 5.3 0.8 1.7 2.4 2.7 4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
// 2
|
||||
{
|
||||
path: 'm 369 96 c -1.7 0 -3.1 1.3 -3.9 2.9 -0.8 1.7 -0.8 3.7 0 5.3 0.8 1.7 2.4 2.7 4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
// 3
|
||||
{
|
||||
path: 'm 110.4 165 c 1.7 0 3.1 1.3 3.9 2.9 0.8 1.7 0.8 3.7 0 5.3 -0.8 1.7 -2.4 2.7 -4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
{
|
||||
path: 'm 56 148 c 0 -1.7 1.3 -3.1 2.9 -3.9 1.7 -0.8 3.7 -0.8 5.3 0 1.7 0.8 2.7 2.4 2.7 4',
|
||||
duration: connectorDuration
|
||||
},
|
||||
// 4
|
||||
{
|
||||
path: 'm 229 236 c -1.7 0 -3.1 1.3 -3.9 2.9 -0.8 1.7 -0.8 3.7 0 5.3 0.8 1.7 2.4 2.7 4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
{
|
||||
path: 'm 331 234.7 c 1.7 0 3.1 1.3 3.9 2.9 0.8 1.7 0.8 3.7 0 5.3 -0.8 1.7 -2.4 2.7 -4 2.7',
|
||||
duration: connectorDuration
|
||||
},
|
||||
{
|
||||
path: 'm 285 251 c 0 1.7 -1.3 3.1 -2.9 3.9 -1.7 0.8 -3.7 0.8 -5.3 0 -1.7 -0.8 -2.7 -2.4 -2.7 -4',
|
||||
duration: connectorDuration
|
||||
},
|
||||
// 5
|
||||
{
|
||||
path: 'm 213 329.5 c 0 -1.7 1.3 -3.1 2.9 -3.9 1.7 -0.8 3.7 -0.8 5.3 0 1.7 0.8 2.7 2.4 2.7 4',
|
||||
duration: connectorDuration
|
||||
},
|
||||
// 6
|
||||
{
|
||||
path: 'm 430 316 c -1.7 0 -3.1 1.3 -3.9 2.9 -0.8 1.7 -0.8 3.7 0 5.3 0.8 1.7 2.4 2.7 4 2.7',
|
||||
duration: connectorDuration
|
||||
}
|
||||
],
|
||||
dimensions: {
|
||||
width: config.mapWidth,
|
||||
height: config.mapHeight
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// draw systems into header
|
||||
$('#' + config.headerConnectionsContainerId).lazylinepainter(
|
||||
{
|
||||
svgData: pathObj,
|
||||
strokeWidth: 2,
|
||||
duration: 600,
|
||||
drawSequential: false,
|
||||
strokeOpacity: 1,
|
||||
overrideKey: 'connectors',
|
||||
strokeJoin: 'miter',
|
||||
strokeCap: 'butt',
|
||||
strokeColor: '#63676A', //gray
|
||||
onComplete: function(){
|
||||
drawConnections(callback);
|
||||
}
|
||||
|
||||
}).lazylinepainter('paint');
|
||||
};
|
||||
|
||||
/**
|
||||
* draw connections layer
|
||||
* @param callback
|
||||
*/
|
||||
let drawConnections = function(callback){
|
||||
|
||||
let connectionDuration = 250;
|
||||
let connectionWidth = 8;
|
||||
let connectionInnerWidth = 4;
|
||||
let connectionBorderColor = '#63676A'; //gray
|
||||
|
||||
let pathObj = {
|
||||
connections: {
|
||||
strokepath: [
|
||||
// connections ====================================================================
|
||||
// 1 - 2
|
||||
{
|
||||
path: 'm 255,40 c 44.5,0 64.2,61.1 109.0,61.15',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionWidth
|
||||
},
|
||||
{
|
||||
path: 'm 255,40 c 44.5,0 64.2,61.1 109.0,61.15',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionInnerWidth,
|
||||
strokeColor: '#3C3F41' // gray
|
||||
},
|
||||
// 2 - 3
|
||||
{
|
||||
path: 'm 146,40.0 c -51.7,0 -83.8,58.8 -83.8,104.5',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionWidth
|
||||
},
|
||||
{
|
||||
path: 'm 146,40.0 c -51.7,0 -83.8,58.8 -83.8,104.5',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionInnerWidth,
|
||||
strokeColor: '#E28A0D' // orange
|
||||
},
|
||||
// 3 - 4
|
||||
{
|
||||
path: 'm 115,171 c 45.7,0 64.1,71.2 109.6,70.8',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionWidth
|
||||
},
|
||||
{
|
||||
path: 'm 115,171 c 45.7,0 64.1,71.2 109.6,70.8',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionInnerWidth,
|
||||
strokeColor: '#A52521' // red
|
||||
},
|
||||
// 4 - 5
|
||||
{
|
||||
path: 'm 279,256 c 0.5,35.9 -60.1,35.1 -60.1,70.0',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionWidth
|
||||
},
|
||||
{
|
||||
path: 'm 279,256 c 0.5,35.9 -60.1,35.1 -60.1,70.0',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionInnerWidth,
|
||||
strokeColor: '#3C3F41' // gray
|
||||
},
|
||||
// 4 - 6
|
||||
{
|
||||
path: 'm 335,240 c 44.2,0 43.7,81.6 89.9,81.6',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionWidth
|
||||
},
|
||||
{
|
||||
path: 'm 335,240 c 44.2,0 43.7,81.6 89.9,81.6',
|
||||
duration: connectionDuration,
|
||||
strokeWidth: connectionInnerWidth,
|
||||
strokeColor: '#3C3F41' // gray
|
||||
}
|
||||
],
|
||||
dimensions: {
|
||||
width: config.mapWidth,
|
||||
height: config.mapHeight
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// draw systems into header
|
||||
$('#' + config.headerSystemConnectorsId).lazylinepainter(
|
||||
{
|
||||
svgData: pathObj,
|
||||
strokeWidth: 2,
|
||||
duration: 600,
|
||||
// drawSequential: false,
|
||||
strokeOpacity: 1,
|
||||
overrideKey: 'connections',
|
||||
strokeJoin: 'miter',
|
||||
strokeCap: 'butt',
|
||||
strokeColor: connectionBorderColor,
|
||||
onComplete: function(){
|
||||
drawBackground(callback);
|
||||
}
|
||||
|
||||
}).lazylinepainter('paint');
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* draw background layer
|
||||
* @param callback
|
||||
*/
|
||||
let drawBackground = function(callback){
|
||||
$('#' + config.headerBackgroundContainerId + ' .' + config.headerSystemClass).velocity('transition.bounceUpIn', {
|
||||
stagger: 150,
|
||||
complete: function(){
|
||||
if(typeof callback === 'function'){
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* draws the demo map
|
||||
* @param callback
|
||||
*/
|
||||
$.fn.drawDemoMap = function(callback){
|
||||
let canvasElement = $(this);
|
||||
|
||||
|
||||
// draw systems
|
||||
drawSystems(callback);
|
||||
};
|
||||
|
||||
});
|
||||
216
public/js/v1.5.2/app/ui/dialog/account_settings.js
Normal file
216
public/js/v1.5.2/app/ui/dialog/account_settings.js
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* user settings/share dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox){
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// select character dialog
|
||||
settingsDialogId: 'pf-settings-dialog', // id for "settings" dialog
|
||||
settingsAccountContainerId: 'pf-settings-dialog-account', // id for the "account" container
|
||||
settingsShareContainerId: 'pf-settings-dialog-share', // id for the "share" container
|
||||
settingsCharacterContainerId: 'pf-settings-dialog-character', // id for the "character" container
|
||||
|
||||
// captcha
|
||||
captchaKeyUpdateAccount: 'SESSION.CAPTCHA.ACCOUNT.UPDATE', // key for captcha reason
|
||||
captchaImageWrapperId: 'pf-dialog-captcha-wrapper', // id for "captcha image" wrapper
|
||||
captchaImageId: 'pf-dialog-captcha-image', // id for "captcha image"
|
||||
|
||||
loadingOptions: { // config for loading overlay
|
||||
icon: {
|
||||
size: 'fa-2x'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* show "register/settings" dialog
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$.fn.showSettingsDialog = function(){
|
||||
|
||||
// check if there are other dialogs open
|
||||
let openDialogs = Util.getOpenDialogs();
|
||||
if(openDialogs.length > 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
requirejs(['text!templates/dialog/settings.html', 'mustache'], function(template, Mustache){
|
||||
|
||||
let data = {
|
||||
id: config.settingsDialogId,
|
||||
settingsAccountContainerId: config.settingsAccountContainerId,
|
||||
settingsShareContainerId: config.settingsShareContainerId,
|
||||
settingsCharacterContainerId: config.settingsCharacterContainerId,
|
||||
userData: Init.currentUserData,
|
||||
captchaImageWrapperId: config.captchaImageWrapperId,
|
||||
captchaImageId: config.captchaImageId,
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass,
|
||||
ccpImageServer: Init.url.ccpImageServer,
|
||||
roleLabel: Util.getLabelByRole(Util.getObjVal(Util.getCurrentUserData(), 'character.role')).prop('outerHTML'),
|
||||
characterAutoLocationSelectEnabled: Boolean(Util.getObjVal(Init, 'character.autoLocationSelect'))
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let accountSettingsDialog = bootbox.dialog({
|
||||
title: 'Account settings',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-check fa-fw"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function(){
|
||||
|
||||
// get the current active form
|
||||
let form = $('#' + config.settingsDialogId).find('form').filter(':visible');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check whether the form is valid
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid === true){
|
||||
let tabFormValues = form.getFormValues();
|
||||
|
||||
// send Tab data and store values
|
||||
let requestData = {
|
||||
formData: tabFormValues
|
||||
};
|
||||
|
||||
accountSettingsDialog.find('.modal-content').showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.saveUserConfig,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all data)
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}else{
|
||||
// store new/updated user data -> update head
|
||||
if(responseData.userData){
|
||||
Util.setCurrentUserData(responseData.userData);
|
||||
}
|
||||
|
||||
form.find('.alert').velocity('transition.slideDownOut',{
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Util.showNotify({title: 'Account saved', type: 'success'});
|
||||
|
||||
// close dialog/menu
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
accountSettingsDialog.modal('hide');
|
||||
}
|
||||
|
||||
}).fail(function(jqXHR, status, error){
|
||||
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveAccountSettings', text: reason, type: 'error'});
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all)
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
|
||||
// check for DB errors
|
||||
if(jqXHR.status === 500){
|
||||
|
||||
if(jqXHR.responseText){
|
||||
let errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
form.showFormMessage(errorObj.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).setProgramStatus('problem');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
accountSettingsDialog.on('show.bs.modal', function(e){
|
||||
// request captcha image and show
|
||||
let captchaImageWrapperContainer = $('#' + config.captchaImageWrapperId);
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyUpdateAccount);
|
||||
|
||||
// init captcha refresh button
|
||||
captchaImageWrapperContainer.find('i').on('click', function(){
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyUpdateAccount);
|
||||
});
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
accountSettingsDialog.on('shown.bs.modal', function(e){
|
||||
let dialogElement = $(this);
|
||||
let form = dialogElement.find('form');
|
||||
|
||||
dialogElement.initTooltips();
|
||||
|
||||
form.initFormValidation();
|
||||
});
|
||||
|
||||
// show dialog
|
||||
accountSettingsDialog.modal('show');
|
||||
|
||||
// events for tab change
|
||||
accountSettingsDialog.find('.navbar a').on('shown.bs.tab', function(e){
|
||||
|
||||
// init "toggle" switches on current active tab
|
||||
accountSettingsDialog.find( $(this).attr('href') ).find('input[data-toggle="toggle"][type="checkbox"]').bootstrapToggle({
|
||||
on: '<i class="fas fa-fw fa-check"></i> Enable',
|
||||
off: 'Disable <i class="fas fa-fw fa-ban"></i>',
|
||||
onstyle: 'success',
|
||||
offstyle: 'warning',
|
||||
width: 100,
|
||||
height: 30
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
});
|
||||
76
public/js/v1.5.2/app/ui/dialog/api_status.js
Normal file
76
public/js/v1.5.2/app/ui/dialog/api_status.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* changelog dialog (GitHub API repository information)
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], ($, Init, Util, Render, bootbox) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
apiStatusDialogClass: 'pf-api-status-dialog' // class for "api status" dialog
|
||||
};
|
||||
|
||||
/**
|
||||
* show api status dialog
|
||||
* @param apiData
|
||||
*/
|
||||
$.fn.apiStatusDialog = function(apiData){
|
||||
|
||||
let data = {
|
||||
apiData: apiData,
|
||||
methodFormat: () => {
|
||||
return (val, render) => {
|
||||
switch(render(val)){
|
||||
case 'get': return 'txt-color-blue';
|
||||
case 'post': return 'txt-color-green';
|
||||
case 'put': return 'txt-color-yellow';
|
||||
case 'delete': return 'txt-color-red';
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
},
|
||||
statusTitle: () => {
|
||||
return (val, render) => {
|
||||
switch(render(val)){
|
||||
case 'green': return 'ok';
|
||||
case 'yellow': return 'degraded: Slow or potentially dropping requests';
|
||||
case 'red': return 'bad: Most requests are not succeeding and/or are very slow (5s+) on average';
|
||||
default: return 'unknown';
|
||||
}
|
||||
};
|
||||
},
|
||||
secondsFormat: () => {
|
||||
return (val, render) => {
|
||||
return parseFloat(render(val)).toFixed(2) + 's';
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/api_status.html', 'mustache'], (template, Mustache) => {
|
||||
let apiStatusDialog = bootbox.dialog({
|
||||
className: config.apiStatusDialogClass,
|
||||
title: 'API status',
|
||||
message: Mustache.render(template, data),
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
apiStatusDialog.initTooltips();
|
||||
|
||||
// show dialog
|
||||
apiStatusDialog.modal('show');
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
140
public/js/v1.5.2/app/ui/dialog/changelog.js
Normal file
140
public/js/v1.5.2/app/ui/dialog/changelog.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* changelog dialog (GitHub API repository information)
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], ($, Init, Util, Render, bootbox) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
changelogDialogClass: 'pf-changelog-dialog', // class for "changelog" dialog
|
||||
dynamicMessageContainerClass: 'pf-dynamic-message-container', // class for "dynamic" (JS) message container
|
||||
timelineClass: 'timeline' // class for "timeline"
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* show version information
|
||||
* @param changelogDialog
|
||||
* @param versionData
|
||||
*/
|
||||
let showVersion = (changelogDialog, versionData) => {
|
||||
let type = 'error';
|
||||
let title = versionData.current;
|
||||
let text = 'Installed version check failed';
|
||||
|
||||
if(versionData.dev){
|
||||
// developer version
|
||||
type = 'info';
|
||||
title = versionData.current + ' (dev)';
|
||||
text = 'This installation is ahead of current stable version <kbd>' + versionData.last + '</kbd>.';
|
||||
}else{
|
||||
// standard version
|
||||
if(versionData.delta === 0){
|
||||
// last stable
|
||||
type = 'success';
|
||||
title = versionData.current;
|
||||
text = 'This installation is up2date.';
|
||||
}else{
|
||||
// outdated...
|
||||
type = 'warning';
|
||||
title = versionData.current;
|
||||
text = 'This installation is ' + versionData.delta + ' version behind current stable <kbd>' + versionData.last + '</kbd>.';
|
||||
}
|
||||
}
|
||||
|
||||
changelogDialog.find('.' + config.dynamicMessageContainerClass).showMessage({
|
||||
dismissible: false,
|
||||
type: type,
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* load changelog information in dialog
|
||||
* @param changelogDialog
|
||||
*/
|
||||
let loadDialogData = (changelogDialog) => {
|
||||
|
||||
// lock dialog
|
||||
let dialogContent = changelogDialog.find('.modal-content');
|
||||
dialogContent.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.gitHubReleases,
|
||||
dataType: 'json',
|
||||
context: {
|
||||
changelogDialog: changelogDialog
|
||||
}
|
||||
}).done(function(data){
|
||||
let changelogDialog = this.changelogDialog;
|
||||
let versionData = data.version;
|
||||
let releasesData = data.releasesData;
|
||||
|
||||
showVersion(changelogDialog, versionData);
|
||||
|
||||
requirejs(['text!templates/ui/timeline_element.html', 'mustache'], function(template, Mustache){
|
||||
for(let i = 0; i < releasesData.length; i++){
|
||||
let releaseData = releasesData[i];
|
||||
|
||||
// template vars
|
||||
let data = {
|
||||
isFirst: (i === 0),
|
||||
isOdd: (i % 2 !== 0),
|
||||
releaseDate: releaseData.publishedAt.substr(0, 10),
|
||||
releaseData: releaseData
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
changelogDialog.find('ul.' + config.timelineClass).append(content);
|
||||
}
|
||||
|
||||
changelogDialog.find('.timeline > li').velocity('transition.expandIn', {
|
||||
stagger: 300,
|
||||
duration: 240,
|
||||
//display: 'auto',
|
||||
complete: function(){}
|
||||
});
|
||||
});
|
||||
}).fail(function(jqXHR, status, error){
|
||||
let reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'});
|
||||
}).always(function(){
|
||||
dialogContent.hideLoadingAnimation();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show changelog dialog
|
||||
*/
|
||||
$.fn.changelogsDialog = function(){
|
||||
let content = $('<div>').append(
|
||||
$('<div>', {
|
||||
class: config.dynamicMessageContainerClass
|
||||
}),
|
||||
$('<ul>', {
|
||||
class: config.timelineClass
|
||||
})
|
||||
);
|
||||
|
||||
let changelogDialog = bootbox.dialog({
|
||||
className: config.changelogDialogClass,
|
||||
title: 'Changelog',
|
||||
size: 'large',
|
||||
message: content
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
changelogDialog.on('shown.bs.modal', function(e){
|
||||
loadDialogData(changelogDialog);
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
51
public/js/v1.5.2/app/ui/dialog/credit.js
Normal file
51
public/js/v1.5.2/app/ui/dialog/credit.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* credits dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox',
|
||||
'app/ui/logo'
|
||||
], function($, Init, Util, Render, bootbox){
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// jump info dialog
|
||||
creditsDialogClass: 'pf-credits-dialog', // class for credits dialog
|
||||
creditsDialogLogoContainerId: 'pf-logo-container' // id for logo element
|
||||
};
|
||||
|
||||
/**
|
||||
* show jump info dialog
|
||||
*/
|
||||
$.fn.showCreditsDialog = function(callback, enableHover){
|
||||
|
||||
requirejs(['text!templates/dialog/credit.html', 'mustache'], function(template, Mustache){
|
||||
|
||||
let data = {
|
||||
logoContainerId: config.creditsDialogLogoContainerId,
|
||||
version: Util.getVersion()
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let creditDialog = bootbox.dialog({
|
||||
className: config.creditsDialogClass,
|
||||
title: 'Licence',
|
||||
message: content
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
creditDialog.on('shown.bs.modal', function(e){
|
||||
|
||||
// load Logo svg
|
||||
creditDialog.find('#' + config.creditsDialogLogoContainerId).drawLogo(callback, enableHover);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
130
public/js/v1.5.2/app/ui/dialog/delete_account.js
Normal file
130
public/js/v1.5.2/app/ui/dialog/delete_account.js
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* delete account dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox'
|
||||
], ($, Init, Util, bootbox) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// global dialog
|
||||
deleteAccountId: 'pf-dialog-delete-account', // dialog id
|
||||
|
||||
// captcha
|
||||
captchaKeyDeleteAccount: 'SESSION.CAPTCHA.ACCOUNT.DELETE', // key for captcha reason
|
||||
captchaImageWrapperId: 'pf-dialog-captcha-wrapper' // id for "captcha image" wrapper
|
||||
};
|
||||
|
||||
/**
|
||||
* shows delete account dialog
|
||||
*/
|
||||
$.fn.showDeleteAccountDialog = function(){
|
||||
|
||||
requirejs(['text!templates/dialog/delete_account.html', 'mustache'], (template, Mustache) => {
|
||||
|
||||
let data = {
|
||||
deleteAccountId: config.deleteAccountId,
|
||||
userData: Util.getCurrentUserData(),
|
||||
captchaImageWrapperId: config.captchaImageWrapperId,
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass
|
||||
};
|
||||
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let deleteAccountDialog = bootbox.dialog({
|
||||
title: 'Delete account',
|
||||
message: content,
|
||||
show: false,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fas fa-user-times fa-fw"></i> delete account',
|
||||
className: 'btn-danger',
|
||||
callback: function(){
|
||||
let dialogElement = $(this);
|
||||
let form = dialogElement.find('form');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
let formValid = form.isValidForm();
|
||||
|
||||
if(formValid){
|
||||
|
||||
let formValues = form.getFormValues();
|
||||
|
||||
if(! $.isEmptyObject(formValues) ){
|
||||
// send Tab data and store values
|
||||
let requestData = {
|
||||
formData: formValues
|
||||
};
|
||||
|
||||
dialogElement.find('.modal-content').showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.deleteAccount,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
dialogElement.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
if(responseData.reroute !== undefined){
|
||||
Util.redirect(responseData.reroute);
|
||||
}else if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyDeleteAccount, function(){
|
||||
form.find('[name="captcha"]').resetFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
}).fail(function(jqXHR, status, error){
|
||||
dialogElement.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
let reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': deleteAccount', text: reason, type: 'error'});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
deleteAccountDialog.on('show.bs.modal', function(e){
|
||||
// request captcha image and show
|
||||
let captchaImageWrapperContainer = $('#' + config.captchaImageWrapperId);
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyDeleteAccount);
|
||||
|
||||
// init captcha refresh button
|
||||
captchaImageWrapperContainer.find('i').on('click', function(){
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyDeleteAccount);
|
||||
});
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
deleteAccountDialog.on('shown.bs.modal', function(e){
|
||||
let dialogElement = $(this);
|
||||
|
||||
dialogElement.initTooltips();
|
||||
});
|
||||
|
||||
// show dialog
|
||||
deleteAccountDialog.modal('show');
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
120
public/js/v1.5.2/app/ui/dialog/jump_info.js
Normal file
120
public/js/v1.5.2/app/ui/dialog/jump_info.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* jump info dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox',
|
||||
], ($, Init, Util, Render, bootbox) => {
|
||||
'use strict';
|
||||
|
||||
let config = {
|
||||
// jump info dialog
|
||||
jumpInfoDialogClass: 'pf-jump-info-dialog', // class for jump info dialog
|
||||
wormholeInfoMassTableClass: 'pf-wormhole-info-mass-table', // class for "wormhole mass" table
|
||||
wormholeInfoJumpTableClass: 'pf-wormhole-info-jump-table' // class for "wormhole jump" table
|
||||
};
|
||||
|
||||
/**
|
||||
* show jump info dialog
|
||||
*/
|
||||
$.fn.showJumpInfoDialog = function(){
|
||||
requirejs(['text!templates/dialog/jump_info.html', 'mustache', 'datatables.loader'], (template, Mustache) => {
|
||||
let data = {
|
||||
config: config,
|
||||
wormholes: Object.keys(Init.wormholes).map(function(k){ return Init.wormholes[k]; }), // convert Json to array
|
||||
securityClass: function(){
|
||||
return function(value, render){
|
||||
return this.Util.getSecurityClassForSystem( render(value) );
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
}),
|
||||
massValue: function(){
|
||||
return function(value, render){
|
||||
let mass = render(value);
|
||||
switch(mass.length){
|
||||
case 0: return '';
|
||||
case 1: return 'Yes';
|
||||
default: return this.Util.formatMassValue(mass);
|
||||
}
|
||||
}.bind(this);
|
||||
}.bind({
|
||||
Util: Util
|
||||
}),
|
||||
formatStatic: function(){
|
||||
return function(value, render){
|
||||
let isStatic = render(value) === 'true';
|
||||
if(isStatic){
|
||||
return '<i class="fas fa-check"></i>';
|
||||
}else{
|
||||
return '';
|
||||
}
|
||||
};
|
||||
},
|
||||
formatTime: function(){
|
||||
return function(value, render){
|
||||
let time = render(value);
|
||||
return time.length ? time + ' h' : 'unknown';
|
||||
};
|
||||
},
|
||||
sigStrengthValue: function(){
|
||||
return function(value, render){
|
||||
let float = render(value);
|
||||
return float.length ? parseFloat(float).toLocaleString() + ' %' : 'unknown';
|
||||
};
|
||||
}
|
||||
};
|
||||
let content = Mustache.render(template, data);
|
||||
|
||||
let jumpDialog = bootbox.dialog({
|
||||
className: config.jumpInfoDialogClass,
|
||||
title: 'Wormhole jump information',
|
||||
message: content,
|
||||
show: false
|
||||
});
|
||||
|
||||
jumpDialog.on('show.bs.modal', function(e){
|
||||
// init dataTable
|
||||
$(this).find('.' + config.wormholeInfoMassTableClass).DataTable({
|
||||
pageLength: 25,
|
||||
lengthMenu: [[10, 20, 25, 30, 40, -1], [10, 20, 25, 30, 40, 'All']],
|
||||
autoWidth: false,
|
||||
language: {
|
||||
emptyTable: 'No wormholes',
|
||||
zeroRecords: 'No wormholes found',
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
columnDefs: [],
|
||||
data: null // use DOM data overwrites [] default -> data.loader.js
|
||||
});
|
||||
|
||||
$(this).find('.' + config.wormholeInfoJumpTableClass).DataTable({
|
||||
pageLength: -1,
|
||||
paging: false,
|
||||
lengthChange: false,
|
||||
ordering: false,
|
||||
searching: false,
|
||||
info: false,
|
||||
autoWidth: false,
|
||||
language: {
|
||||
emptyTable: 'No wormholes',
|
||||
zeroRecords: 'No wormholes found',
|
||||
lengthMenu: 'Show _MENU_ wormholes',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ wormholes'
|
||||
},
|
||||
columnDefs: [],
|
||||
data: null // use DOM data overwrites [] default -> data.loader.js
|
||||
});
|
||||
});
|
||||
|
||||
jumpDialog.initTooltips();
|
||||
|
||||
jumpDialog.modal('show');
|
||||
});
|
||||
};
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user