Skip to content

Instantly share code, notes, and snippets.

@gbrault
Created February 27, 2018 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbrault/98548a18a3754048d1e38ef61db55812 to your computer and use it in GitHub Desktop.
Save gbrault/98548a18a3754048d1e38ef61db55812 to your computer and use it in GitHub Desktop.
split a window into four adjustable divisions
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
(function () {
/**
* THIS OBJECT WILL ONLY WORK IF your target is positioned relative or absolute,
* or anything that works with the top and left css properties (not static).
*
* Howto
* ============
*
* document.getElementById('my_target').sdrag();
*
* onDrag, onStop
* -------------------
* document.getElementById('my_target').sdrag(onDrag, null);
* document.getElementById('my_target').sdrag(null, onStop);
* document.getElementById('my_target').sdrag(onDrag, onStop);
*
* Both onDrag and onStop callback take the following arguments:
*
* - el, the currentTarget element (#my_target in the above examples)
* - pageX: the mouse event's pageX property (horizontal position of the mouse compared to the viewport)
* - startX: the distance from the element's left property to the horizontal mouse position in the viewport.
* Usually, you don't need to use that property; it is internally used to fix the undesirable
* offset that naturally occurs when you don't drag the element by its top left corner
* (for instance if you drag the element from its center).
* - pageY: the mouse event's pageX property (horizontal position of the mouse compared to the viewport)
* - startY: same as startX, but for the vertical axis (and element's top property)
*
*
*
* The onDrag callback accepts an extra argument: fix.
*
* fix is an array used to fix the coordinates applied to the target.
*
* It can be used to constrain the movement of the target inside of a virtual rectangle area for instance.
* Put a variable in the fix array to override it.
* The possible keys are:
*
* - pageX
* - startX
* - pageY
* - startY
* - skipX
* - skipY
*
* skipX and skipY let you skip the updating of the target's left property.
* This might be required in some cases where the positioning of the target
* is automatically done by the means of other css properties.
*
*
*
*
*
*
* Direction
* -------------
* With direction, you can constrain the drag to one direction only: horizontal or vertical.
* Accepted values are:
*
* - <undefined> (the default)
* - vertical
* - horizontal
*
*
*
*
*/
// simple drag
function sdrag(onDrag, onStop, direction) {
var startX = 0;
var startY = 0;
var el = this;
var dragging = false;
function move(e) {
var fix = {};
onDrag && onDrag(el, e.pageX, startX, e.pageY, startY, fix);
if ('vertical' !== direction) {
var pageX = ('pageX' in fix) ? fix.pageX : e.pageX;
if ('startX' in fix) {
startX = fix.startX;
}
if (false === ('skipX' in fix)) {
el.style.left = (pageX - startX) + 'px';
}
}
if ('horizontal' !== direction) {
var pageY = ('pageY' in fix) ? fix.pageY : e.pageY;
if ('startY' in fix) {
startY = fix.startY;
}
if (false === ('skipY' in fix)) {
el.style.top = (pageY - startY) + 'px';
}
}
}
function startDragging(e) {
if (e.currentTarget instanceof HTMLElement || e.currentTarget instanceof SVGElement) {
dragging = true;
var left = el.style.left ? parseInt(el.style.left) : 0;
var top = el.style.top ? parseInt(el.style.top) : 0;
startX = e.pageX - left;
startY = e.pageY - top;
window.addEventListener('mousemove', move);
}
else {
throw new Error("Your target must be an html element");
}
}
this.addEventListener('mousedown', startDragging);
window.addEventListener('mouseup', function (e) {
if (true === dragging) {
dragging = false;
window.removeEventListener('mousemove', move);
onStop && onStop(el, e.pageX, startX, e.pageY, startY);
}
});
}
Element.prototype.sdrag = sdrag;
})();
</script>
<style type="text/css">
html,
body {
height: 100%;
}
.panes-container {
display: flex;
width: 100%;
overflow: hidden;
}
.left-pane {
width: 49%;
background: #ccc;
}
.u-pane {
height: 49%;
background: #fff;
}
.panes-separator {
width: 0.5%;
background: red;
position: relative;
cursor: col-resize;
}
.h-panes-separator {
height: 0.5%;
background: red;
position: relative;
cursor: row-resize;
}
.right-pane {
flex: auto;
background: #eee;
}
.d-plane {
flex: auto;
}
.panes-container,
.panes-separator,
.left-pane,
.right-pane
{
margin: 0;
padding: 0;
height: 100%;
}
.u-pane,
.d-pane
{
margin: 0;
padding: 0;
width: 100%;
}
</style>
</head>
<body>
<div class="panes-container">
<div class="left-pane" id="left-pane">
<div class="u-pane" id="uleft-pane">
<p>I'm the up-left pane</p>
</div>
<div class="h-panes-separator" id="sleft-pane"></div>
<div class="d-pane" id="dleft-pane">
<p>I'm the down-left pane</p>
</div>
</div>
<div class="panes-separator" id="panes-separator"></div>
<div class="right-pane" id="right-pane">
<div class="u-pane" id="uright-pane">
<p>I'm the up-right pane</p>
</div>
<div class="h-panes-separator" id="sright-pane"></div>
<div class="d-pane" id="dright-pane">
<p>I'm the down-right pane</p>
</div>
</div>
</div>
<script>
var uleftPane = document.getElementById('uleft-pane');
var dleftPane = document.getElementById('dleft-pane');
var sleftPane = document.getElementById('sleft-pane');
var leftPane = document.getElementById('left-pane');
var urightPane = document.getElementById('uright-pane');
var drightPane = document.getElementById('dright-pane');
var srightPane = document.getElementById('sright-pane');
var rightPane = document.getElementById('right-pane');
var paneSep = document.getElementById('panes-separator');
// The script below constrains the target to move horizontally between a left and a right virtual boundaries.
// - the left limit is positioned at 10% of the screen width
// - the right limit is positioned at 90% of the screen width
var leftLimit = 10;
var rightLimit = 90;
paneSep.sdrag(function(el, pageX, startX, pageY, startY, fix) {
fix.skipX = true;
if (pageX < window.innerWidth * leftLimit / 100) {
pageX = window.innerWidth * leftLimit / 100;
fix.pageX = pageX;
}
if (pageX > window.innerWidth * rightLimit / 100) {
pageX = window.innerWidth * rightLimit / 100;
fix.pageX = pageX;
}
var cur = pageX / window.innerWidth * 100;
if (cur < 0) {
cur = 0;
}
if (cur > window.innerWidth) {
cur = window.innerWidth;
}
var right = (100 - cur - 2);
leftPane.style.width = cur + '%';
rightPane.style.width = right + '%';
}, null, 'horizontal');
var upLimit = 10;
var downLimit = 90;
sleftPane.sdrag(function(el, pageX, startX, pageY, startY, fix) {
fix.skipY = true;
if (pageY < window.innerHeight * upLimit / 100) {
pageY = window.innerHeight * upLimit / 100;
fix.pageY = pageY;
}
if (pageY > window.innerHeight * downLimit / 100) {
pageY = window.innerHeight * downLimit / 100;
fix.pageY = pageY;
}
var cur = pageY / window.innerHeight * 100;
if (cur < 0) {
cur = 0;
}
if (cur > window.innerHeight) {
cur = window.innerHeight;
}
var down = (100 - cur - 2);
uleftPane.style.height = cur + '%';
dleftPane.style.height = down + '%';
}, null, 'vertical');
srightPane.sdrag(function(el, pageX, startX, pageY, startY, fix) {
fix.skipY = true;
if (pageY < window.innerHeight * upLimit / 100) {
pageY = window.innerHeight * upLimit / 100;
fix.pageY = pageY;
}
if (pageY > window.innerHeight * downLimit / 100) {
pageY = window.innerHeight * downLimit / 100;
fix.pageY = pageY;
}
var cur = pageY / window.innerHeight * 100;
if (cur < 0) {
cur = 0;
}
if (cur > window.innerHeight) {
cur = window.innerHeight;
}
var down = (100 - cur - 2);
urightPane.style.height = cur + '%';
drightPane.style.height = down + '%';
}, null, 'vertical');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment