element-web/src/resizer/resizer.js

100 lines
3.3 KiB
JavaScript
Raw Normal View History

import {Sizer} from "./sizer";
/*
classNames:
// class on resize-handle
handle: string
// class on resize-handle
reverse: string
// class on resize-handle
vertical: string
// class on container
resizing: string
*/
export class Resizer {
constructor(container, distributorCtor, distributorCfg, sizerCtor = Sizer) {
this.container = container;
this.distributorCtor = distributorCtor;
this.distributorCfg = distributorCfg;
this.sizerCtor = sizerCtor;
this.classNames = {
handle: "resizer-handle",
reverse: "resizer-reverse",
vertical: "resizer-vertical",
resizing: "resizer-resizing",
};
this.mouseDownHandler = (event) => this._onMouseDown(event);
}
setClassNames(classNames) {
this.classNames = classNames;
}
attach() {
this.container.addEventListener("mousedown", this.mouseDownHandler, false);
}
detach() {
this.container.removeEventListener("mousedown", this.mouseDownHandler, false);
}
_isResizeHandle(el) {
return el && el.classList.contains(this.classNames.handle);
}
_onMouseDown(event) {
const target = event.target;
if (!this._isResizeHandle(target) || target.parentElement !== this.container) {
return;
}
// prevent starting a drag operation
event.preventDefault();
// mark as currently resizing
if (this.classNames.resizing) {
this.container.classList.add(this.classNames.resizing);
}
const resizeHandle = event.target;
const vertical = resizeHandle.classList.contains(this.classNames.vertical);
const reverse = resizeHandle.classList.contains(this.classNames.reverse);
const sizer = new this.sizerCtor(this.container, vertical, reverse);
const items = this._getResizableItems();
const prevItem = resizeHandle.previousElementSibling;
// if reverse, resize the item after the handle, so + 1
const itemIndex = items.indexOf(prevItem) + (reverse ? 1 : 0);
const item = items[itemIndex];
const distributor = new this.distributorCtor(
sizer, item, this.distributorCfg,
items, this.container);
const onMouseMove = (event) => {
const offset = sizer.offsetFromEvent(event);
distributor.resize(offset);
};
const body = document.body;
const onMouseUp = (event) => {
if (this.classNames.resizing) {
this.container.classList.remove(this.classNames.resizing);
}
const offset = sizer.offsetFromEvent(event);
distributor.finish(offset);
body.removeEventListener("mouseup", onMouseUp, false);
body.removeEventListener("mousemove", onMouseMove, false);
};
body.addEventListener("mouseup", onMouseUp, false);
body.addEventListener("mousemove", onMouseMove, false);
}
_getResizableItems() {
return Array.from(this.container.children).filter(el => {
return !this._isResizeHandle(el) && (
this._isResizeHandle(el.previousElementSibling) ||
this._isResizeHandle(el.nextElementSibling));
});
}
}