You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.1 KiB
156 lines
5.1 KiB
var borderLayout = function (root, onStateChanged) {
|
|
var dragging;
|
|
var area = {
|
|
north: {element: root.querySelector('.north')},
|
|
south: {element: root.querySelector('.south')},
|
|
west: {element: root.querySelector('.west')},
|
|
east: {element: root.querySelector('.east')},
|
|
center: {element: root.querySelector('.center')}
|
|
};
|
|
setInitSize('north', root.offsetHeight);
|
|
setInitSize('south', root.offsetHeight);
|
|
setInitSize('west', root.offsetWidth);
|
|
setInitSize('east', root.offsetWidth);
|
|
redraw();
|
|
addDrag('north', 'bottom', {left: '0', bottom: '0', width: '100%', cursor: 'ns-resize'}, function (e) {
|
|
return this.origSize + e.clientY - this.origY;
|
|
});
|
|
addDrag('south', 'top', {left: '0', top: '0', width: '100%', cursor: 'ns-resize'}, function (e) {
|
|
return this.origSize - e.clientY + this.origY;
|
|
});
|
|
addDrag('west', 'right', {right: '0', top: '0', height: '100%', cursor: 'ew-resize'}, function (e) {
|
|
return this.origSize + e.clientX - this.origX;
|
|
});
|
|
addDrag('east', 'left', {left: '0', top: '0', height: '100%', cursor: 'ew-resize'}, function (e) {
|
|
return this.origSize - e.clientX + this.origX;
|
|
});
|
|
root.addEventListener('mousemove', function (e) {
|
|
if (dragging) {
|
|
var target = area[dragging.target];
|
|
target.size = Math.min(target.maxSize, Math.max(target.minSize, dragging.size(e)));
|
|
redraw();
|
|
}
|
|
});
|
|
root.addEventListener('mouseup', function (e) {
|
|
dragEnded(onStateChanged);
|
|
});
|
|
root.addEventListener('mouseout', function (e) {
|
|
if (e.target === root) {
|
|
dragEnded(onStateChanged);
|
|
}
|
|
});
|
|
|
|
return {
|
|
resize: resize,
|
|
maximize: maximize,
|
|
minimize: minimize,
|
|
hide: hide
|
|
};
|
|
|
|
function resize(size) {
|
|
for (var prop in size) {
|
|
area[prop].size = size[prop];
|
|
}
|
|
redraw();
|
|
}
|
|
|
|
function maximize(name) {
|
|
setSize(name, area[name].maxSize);
|
|
}
|
|
|
|
function minimize(name) {
|
|
setSize(name, area[name].minSize);
|
|
}
|
|
|
|
function hide(name) {
|
|
setSize(name, 0);
|
|
}
|
|
|
|
function setSize(name, size) {
|
|
area[name].size = size;
|
|
redraw();
|
|
}
|
|
|
|
function setInitSize(name, parent) {
|
|
var elem = area[name].element;
|
|
if (elem) {
|
|
area[name].size = unitToPx(elem.getAttribute('size') || '20%', parent);
|
|
area[name].minSize = unitToPx(elem.getAttribute('min-size') || '5px', parent);
|
|
area[name].maxSize = unitToPx(elem.getAttribute('max-size') || '40%', parent);
|
|
}
|
|
}
|
|
|
|
function unitToPx(value, parent) {
|
|
if (endsWith(value, 'px')) {
|
|
return parseInt(value);
|
|
}
|
|
if (endsWith(value, '%')) {
|
|
return parseInt(value) / 100 * parent;
|
|
}
|
|
}
|
|
|
|
function endsWith(s, end) {
|
|
return s.substring(s.length - end.length) === end;
|
|
}
|
|
|
|
function redraw() {
|
|
setSizeAttr('north', {height: 'north'});
|
|
setSizeAttr('south', {height: 'south'});
|
|
setSizeAttr('west', {width: 'west', paddingTop: 'north', paddingBottom: 'south'});
|
|
setSizeAttr('east', {width: 'east', paddingTop: 'north', paddingBottom: 'south'});
|
|
setSizeAttr('center', {paddingTop: 'north', paddingLeft: 'west', paddingBottom: 'south', paddingRight: 'east'});
|
|
}
|
|
|
|
function setSizeAttr(target, value) {
|
|
var elem = area[target].element;
|
|
if (elem) {
|
|
for (var prop in value) {
|
|
elem.style[prop] = area[value[prop]].size + 'px';
|
|
}
|
|
}
|
|
}
|
|
|
|
function getSize(target, attr) {
|
|
var elem = area[target].element;
|
|
return elem && parseInt(elem[attr]);
|
|
}
|
|
|
|
function addDrag(name, dragSide, style, sizeFn) {
|
|
var target = area[name].element;
|
|
if (target && target.classList.contains('resizable')) {
|
|
var drag = document.createElement('div');
|
|
drag.className = 'drag';
|
|
Object.assign(drag.style, style);
|
|
target.appendChild(drag);
|
|
var borderWidth = parseInt(getComputedStyle(drag)['border-top-width']);
|
|
target.querySelector('.content').style['border' + capital(dragSide)] = 2 * borderWidth + 'px solid transparent';
|
|
drag.addEventListener('mousedown', function (e) {
|
|
dragging = {
|
|
target: name,
|
|
origX: e.clientX,
|
|
origY: e.clientY,
|
|
origSize: area[name].size
|
|
};
|
|
dragging.size = sizeFn.bind(dragging);
|
|
});
|
|
}
|
|
}
|
|
|
|
function capital(s) {
|
|
return s.charAt(0).toUpperCase() + s.substring(1);
|
|
}
|
|
|
|
function dragEnded(listener) {
|
|
if (dragging) {
|
|
if (listener) {
|
|
listener({
|
|
north: getSize('north', 'offsetHeight'),
|
|
south: getSize('south', 'offsetHeight'),
|
|
west: getSize('west', 'offsetWidth'),
|
|
east: getSize('east', 'offsetWidth')
|
|
});
|
|
}
|
|
dragging = null;
|
|
}
|
|
}
|
|
};
|
|
|