192 lines
5.6 KiB
JavaScript
192 lines
5.6 KiB
JavaScript
define([
|
|
'jquery',
|
|
'mousewheel',
|
|
'customScrollbar'
|
|
], ($) => {
|
|
'use strict';
|
|
|
|
let defaultConfig = {
|
|
axis: 'yx',
|
|
theme: 'light-3' ,
|
|
scrollInertia: 200,
|
|
autoExpandScrollbar: false,
|
|
scrollButtons:{
|
|
enable: true,
|
|
scrollAmount: 30,
|
|
scrollType: 'stepless'
|
|
},
|
|
callbacks: {
|
|
onTotalScrollOffset: 0,
|
|
onTotalScrollBackOffset: 0,
|
|
alwaysTriggerOffsets: true
|
|
},
|
|
|
|
advanced: {
|
|
autoUpdateTimeout: 120, // auto-update timeout (default: 60)
|
|
updateOnContentResize: true,
|
|
autoExpandHorizontalScroll: false, // on resize css scale() scroll content should not change
|
|
//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 map scrollbar
|
|
* @param scrollWrapper
|
|
* @param config
|
|
*/
|
|
let initScrollbar = (scrollWrapper, config) => {
|
|
config = $.extend(true, {}, defaultConfig, config);
|
|
|
|
scrollWrapper.mCustomScrollbar(config);
|
|
};
|
|
|
|
/**
|
|
* get mCustomScrollbar container
|
|
* @param element
|
|
* @returns {*|[]}
|
|
*/
|
|
let getContainer = element => element.parents('.mCSB_container');
|
|
|
|
/**
|
|
*
|
|
* @param container
|
|
* @param element
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let getElementPos = (container, element) => {
|
|
return {
|
|
x: element.offset().left - container.offset().left,
|
|
y: element.offset().top - container.offset().top
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @param element
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let getElementDim = element => {
|
|
return {
|
|
x: element.outerWidth(false),
|
|
y: element.outerHeight(false)
|
|
};
|
|
};
|
|
|
|
/**
|
|
* check if an element is 100% visible
|
|
* -> scrolled into viewport
|
|
* @param element
|
|
* @returns {boolean}
|
|
*/
|
|
let isInView = element => {
|
|
let container = getContainer(element);
|
|
let wrapper = container.parent();
|
|
let cPos = {x: container[0].offsetLeft, y: container[0].offsetTop};
|
|
let ePos = getElementPos(container, element);
|
|
let eDim = getElementDim(element);
|
|
|
|
return cPos.y + ePos.y >= 0 &&
|
|
cPos.y + ePos.y < wrapper.height() - eDim.y &&
|
|
cPos.x + ePos.x >= 0 &&
|
|
cPos.x + ePos.x < wrapper.width() - eDim.x;
|
|
};
|
|
|
|
/**
|
|
* get new scrollTo coordinates to center element in viewport
|
|
* @param element
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let getCenterScrollPosition = element => {
|
|
let container = getContainer(element);
|
|
let wrapper = container.parent();
|
|
let cDim = getElementDim(container);
|
|
let wDim = {x: wrapper.width(), y: wrapper.height()};
|
|
let eDim = getElementDim(element);
|
|
let ePos = getElementPos(container, element);
|
|
|
|
let eOff = {
|
|
x: (-wDim.x / 2) + (eDim.x / 2),
|
|
y: (-wDim.y / 2) + (eDim.y / 2)
|
|
};
|
|
|
|
return adjustPos(addOffset(ePos, eOff), cDim);
|
|
};
|
|
|
|
/**
|
|
* scroll to a specific position on map
|
|
* demo: http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/scrollTo_demo.html
|
|
* @param scrollWrapper
|
|
* @param position
|
|
* @param options
|
|
*/
|
|
let scrollToPosition = (scrollWrapper, position, options) => {
|
|
$(scrollWrapper).mCustomScrollbar('scrollTo', position, options);
|
|
};
|
|
|
|
/**
|
|
* scroll to center an element
|
|
* -> subtract some offset for tooltips/connections
|
|
* @param scrollWrapper
|
|
* @param element
|
|
*/
|
|
let scrollToCenter = (scrollWrapper, element) => {
|
|
// no scroll if element is already FULL visible in scrollable viewport
|
|
if(!isInView(element)){
|
|
// get scrollTo position for centered element
|
|
scrollToPosition(scrollWrapper, getCenterScrollPosition(element));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* add/subtract offset coordinates from position
|
|
* @param {{x: number, y: number}} position
|
|
* @param {{x: number, y: number}} offset
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let addOffset = (position, offset) => mapObject(position, (v, k) => v + offset[k]);
|
|
|
|
/**
|
|
* round position
|
|
* @param {{x: number, y: number}} position
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let roundPos = position => mapObject(position, Math.round);
|
|
|
|
/**
|
|
*
|
|
* @param {{x: number, y: number}} position
|
|
* @param {{x: number, y: number}} dimension
|
|
* @returns {{x: number, y: number}}
|
|
*/
|
|
let adjustPos = (position, dimension) => mapObject(roundPos(position), (v, k) => Math.max(1, Math.min(dimension[k], v)) );
|
|
|
|
/**
|
|
* like Array.map() for objects
|
|
* -> callback f is called for each property
|
|
* @see https://stackoverflow.com/a/38829074/4329969
|
|
* @param o
|
|
* @param f
|
|
* @returns {Object}
|
|
*/
|
|
let mapObject = (o, f) => Object.assign(...Object.entries(o).map(([k, v]) => ({[k]: f(v, k) })));
|
|
|
|
return {
|
|
initScrollbar: initScrollbar,
|
|
scrollToPosition: scrollToPosition,
|
|
scrollToCenter: scrollToCenter
|
|
};
|
|
}); |