224 lines
6.9 KiB
JavaScript
224 lines
6.9 KiB
JavaScript
/**
|
|
* Map "magnetizing" feature
|
|
* jsPlumb extension used: https://github.com/ThomasChan/farahey
|
|
*/
|
|
|
|
define([
|
|
'jquery',
|
|
'app/map/util',
|
|
'farahey'
|
|
], ($, MapUtil) => {
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* active magnetizer instances (cache object)
|
|
* @type {{}}
|
|
*/
|
|
let magnetizerInstances = {};
|
|
|
|
/**
|
|
* magnetizer instance exists for mapId
|
|
* @param mapId
|
|
* @returns {boolean}
|
|
*/
|
|
let hasInstance = mapId => magnetizerInstances.hasOwnProperty(mapId);
|
|
|
|
/**
|
|
* get magnetizer instance by mapId
|
|
* @param mapId
|
|
* @returns {null}
|
|
*/
|
|
let getInstance = mapId => hasInstance(mapId) ? magnetizerInstances[mapId] : null;
|
|
|
|
/**
|
|
* set new magnetizer instance for mapId
|
|
* @param mapId
|
|
* @param magnetizer
|
|
*/
|
|
let setInstance = (mapId, magnetizer) => {
|
|
if(mapId && magnetizer){
|
|
magnetizerInstances[mapId] = magnetizer;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* init new magnetizer instance for a map
|
|
* @param mapContainer
|
|
*/
|
|
let initMagnetizer = mapContainer => {
|
|
let mapId = mapContainer.data('id');
|
|
|
|
if(!hasInstance(mapId)){
|
|
// magnetizer not exist -> new instance
|
|
let systems = mapContainer.getSystems();
|
|
|
|
/**
|
|
* function that takes an element from your list and returns its position as a JS object
|
|
* @param system
|
|
* @returns {{top: number, left: number}}
|
|
* @private
|
|
*/
|
|
let _offset = system => {
|
|
let _ = p => {
|
|
let v = system.style[p];
|
|
return parseInt(v.substring(0, v.length - 2));
|
|
};
|
|
return {left: _('left'), top: _('top')};
|
|
};
|
|
|
|
/**
|
|
* function that takes an element id and position, and applies that position to the related element
|
|
* @param system
|
|
* @param o
|
|
* @private
|
|
*/
|
|
let _setOffset = (system, o) => {
|
|
o.left = Math.round(o.left);
|
|
o.top = Math.round(o.top);
|
|
let left = o.left + 'px';
|
|
let top = o.top + 'px';
|
|
let markAsUpdated = false;
|
|
|
|
// new position must be within parent container
|
|
// no negative offset!
|
|
if(
|
|
o.left >= 0 && o.left <= 2300 &&
|
|
system.style.left !== left
|
|
){
|
|
system.style.left = left;
|
|
markAsUpdated = true;
|
|
}
|
|
|
|
if(
|
|
o.top >= 0 && o.top <= 1400 &&
|
|
system.style.top !== top
|
|
){
|
|
system.style.top = top;
|
|
markAsUpdated = true;
|
|
}
|
|
|
|
if(markAsUpdated){
|
|
MapUtil.markAsChanged($(system));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* filter some element8s) from being moved
|
|
* @param systemId
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
let _dragFilter = systemId => {
|
|
let filterClasses = ['jtk-drag', MapUtil.config.systemLockedClass];
|
|
return ![...document.getElementById(systemId).classList].some(className => filterClasses.indexOf(className) >= 0);
|
|
};
|
|
|
|
/**
|
|
* grid snap constraint
|
|
* @param gridX
|
|
* @param gridY
|
|
* @returns {Function}
|
|
*/
|
|
let gridConstrain = (gridX, gridY) => {
|
|
return (id, current, delta) => {
|
|
if(mapContainer.hasClass(MapUtil.config.mapGridClass)){
|
|
// active grid
|
|
return {
|
|
left: (gridX * Math.floor( (Math.round(current[0]) + delta.left) / gridX )) - current[0],
|
|
top: (gridY * Math.floor( (Math.round(current[1]) + delta.top) / gridY )) - current[1]
|
|
};
|
|
}else{
|
|
// no grid
|
|
delta.left = Math.round(delta.left);
|
|
delta.top = Math.round(delta.top);
|
|
return delta;
|
|
}
|
|
};
|
|
};
|
|
|
|
// create new magnetizer instance -------------------------------------------------------------------------
|
|
setInstance(mapId, window.Farahey.getInstance({
|
|
container: mapContainer,
|
|
getContainerPosition: mapContainer => mapContainer.offset(),
|
|
getPosition:_offset,
|
|
getSize: system => {
|
|
let clientRect = system.getBoundingClientRect();
|
|
return [Math.floor(clientRect.width), Math.floor(clientRect.height)];
|
|
},
|
|
getId : system => system.id,
|
|
setPosition:_setOffset,
|
|
elements: systems.toArray(),
|
|
filter: _dragFilter,
|
|
padding: [3, 3],
|
|
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension),
|
|
executeNow: false, // no initial rearrange after initialization
|
|
excludeFocus: true
|
|
}));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* destroy Magnetizer instance
|
|
*/
|
|
let destroyMagnetizer = mapContainer => {
|
|
let mapId = mapContainer.data('id');
|
|
let magnetizer = getInstance(mapId);
|
|
if(magnetizer){
|
|
magnetizer.reset();
|
|
delete magnetizerInstances[mapId];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* update system positions for "all" systems that are effected by drag&drop
|
|
* @param map
|
|
* @param e
|
|
*/
|
|
let executeAtEvent = (map, e) => {
|
|
let mapContainer = $(map.getContainer());
|
|
let mapId = mapContainer.data('id');
|
|
let magnetizer = getInstance(mapId);
|
|
|
|
if(magnetizer && e){
|
|
magnetizer.executeAtEvent(e, {
|
|
iterations: 2,
|
|
excludeFocus: true
|
|
});
|
|
map.repaintEverything();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* add system to magnetizer instance
|
|
* @param mapId
|
|
* @param system
|
|
* @param doNotTestForDuplicates
|
|
*/
|
|
let addElement = (mapId, system, doNotTestForDuplicates) => {
|
|
let magnetizer = getInstance(mapId);
|
|
if(magnetizer){
|
|
magnetizer.addElement(system, doNotTestForDuplicates);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* remove system element from magnetizer instance
|
|
* @param mapId
|
|
* @param system
|
|
*/
|
|
let removeElement = (mapId, system) => {
|
|
let magnetizer = getInstance(mapId);
|
|
if(magnetizer){
|
|
magnetizer.removeElement(system);
|
|
}
|
|
};
|
|
|
|
return {
|
|
initMagnetizer: initMagnetizer,
|
|
destroyMagnetizer: destroyMagnetizer,
|
|
executeAtEvent: executeAtEvent,
|
|
addElement: addElement,
|
|
removeElement: removeElement
|
|
};
|
|
}); |