Skip to content

Commit

Permalink
0.0.0-4
Browse files Browse the repository at this point in the history
  • Loading branch information
crosshj committed Jul 10, 2022
1 parent 25c0437 commit 08c36ec
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 119 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ see <a href="./test/index.html">test/index.html</a> for a more involved example

## Summary
This layout system uses css grid to position elements.
It is written from scratch to be simple, flexible, and dependency-free.
It is written from scratch to be simple, flexible, and dependency-free.

## TODO
- move tab-related things out of editor.html and into module
- drag listener should use global state for drag meta-data (not event data)
- drag listener should only allow one hover target to exist at a time (one pane at a time)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fiug/layout",
"version": "0.0.0-3",
"version": "0.0.0-4",
"description": "page layout for browser applications",
"main": "dist/layout.js",
"scripts": {
Expand Down
149 changes: 149 additions & 0 deletions src/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const pointerDown = (sizer, index, resize) => (e) => {
let { x: startX, y: startY } = e;
sizer.setPointerCapture(e.pointerId);

const pointerMove = (e) => {
resize(sizer, index, e.x - startX, e.y - startY);
startX = e.x;
startY = e.y;
};
const pointerUp = () => {
document.removeEventListener('pointermove', pointerMove);
document.removeEventListener('pointerup', pointerUp);
document.removeEventListener('pointercancel', pointerUp);
};
document.addEventListener('pointermove', pointerMove);
document.addEventListener('pointerup', pointerUp);
document.addEventListener('pointercancel', pointerUp);
};

const dragStartMessage = () => (e) => {
const { source, dragStart } = JSON.parse(e.data);
console.log(source, dragStart);
};

export const attachResizeListener = (sizer, index, resize) => {
sizer.addEventListener('pointerdown', pointerDown(sizer, index, resize));
};

export const attachDragListener = () => {
window.addEventListener('message', dragStartMessage());
};

export const dragStart = (ev) => {
ev.dataTransfer.setData("text", ev.target.textContent);
const message = JSON.stringify({
dragStart: ev.target.textContent,
source: location.href.split('/').pop()
});
window.parent.postMessage(message, '*');
};


//------------------------------------------
const dropStyle = `
.hidden { display: none; }
.drag-hover {
background: #008062 !important;
/*filter: hue-rotate(294deg) brightness(0.75) saturate(0.25);*/
}
.dropped { background: blue; }
.mouse { position: absolute; bottom: 5px; right: 5px; }
.drag-target {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #7774;
transition: left .3s, right .3s, top .3s, bottom .3s;
}
.right-hover { left: 50%; }
.left-hover { right: 50%; }
.bottom-hover { top: 50%; }
.top-hover { bottom: 50%; }
`;
export const onDrop = (handler) => {
const HOVER_WAIT_TIME = 750;

const mouse = document.createElement('div');
mouse.classList.add('mouse');
document.body.append(mouse);

const dragTarget = document.createElement('div');
dragTarget.classList.add('drag-target', 'hidden');
dragTarget.innerHTML = `<style>${dropStyle}</style>`
document.body.append(dragTarget);

let hoverClassWait;
function hoverClassForSplit(x,y){
if(x < 0.25) return 'left-hover';
if(x > 0.75) return 'right-hover';
if(y < 0.25) return 'top-hover';
if(y > 0.75) return 'bottom-hover';
return '';
}
function removeHoverClasses(el){
el.classList.remove('left-hover');
el.classList.remove('right-hover');
el.classList.remove('top-hover');
el.classList.remove('bottom-hover');
}

const dragover = (ev) => {
dragTarget.classList.remove('hidden');
ev.preventDefault();

const mousePercents = [
ev.clientX/document.body.clientWidth,
ev.clientY/document.body.clientHeight
];
mouse.innerHTML = `${
hoverClassWait === "done"
? 'DONE'
: 'WAIT'
} : ${
(100 * mousePercents[0]).toFixed(2)
}, ${
(100 * mousePercents[1]).toFixed(2)
}`;

if(!hoverClassWait){
hoverClassWait="inprogress";
setTimeout(() => {
if(hoverClassWait==="inprogress")
hoverClassWait = "done";
}, HOVER_WAIT_TIME);
}
if(hoverClassWait==="inprogress") return;

const hoverClass = hoverClassForSplit(...mousePercents);
if(!hoverClass) removeHoverClasses(dragTarget);
if(hoverClass && !dragTarget.classList.contains(hoverClass)){
removeHoverClasses(dragTarget);
dragTarget.classList.add(hoverClass);
}
};
//document.body.ondragover = editor.ondragover = dragover;
document.body.ondragover = dragover;
document.body.ondrop = (ev) => {
ev.preventDefault();
const data = ev.dataTransfer.getData("text");
//document.body.classList.remove('drag-hover');
dragTarget.classList.add('hidden');
mouse.innerHTML = '';
removeHoverClasses(dragTarget);
hoverClassWait = undefined;
handler({ name: data });
};
dragTarget.ondragleave = (ev) => {
ev.preventDefault();
dragTarget.classList.add('hidden');
mouse.innerHTML = '';
removeHoverClasses(dragTarget);
hoverClassWait = undefined;
//document.body.classList.remove('drag-hover');
};

return { dragover };
};
31 changes: 7 additions & 24 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ https://blog.jim-nielsen.com/2021/css-system-colors/
https://css-tricks.com/snippets/css/complete-guide-grid/
*/

import * as events from './events.js';

const style = `
.page-layout {
display: grid;
Expand All @@ -23,29 +25,6 @@ const style = `
}
`;

const pointerDown = (sizer, index, resize) => (e) => {
let { x: startX, y: startY } = e;
sizer.setPointerCapture(e.pointerId);

const pointerMove = (e) => {
resize(sizer, index, e.x - startX, e.y - startY);
startX = e.x;
startY = e.y;
};
const pointerUp = () => {
document.removeEventListener('pointermove', pointerMove);
document.removeEventListener('pointerup', pointerUp);
document.removeEventListener('pointercancel', pointerUp);
};
document.addEventListener('pointermove', pointerMove);
document.addEventListener('pointerup', pointerUp);
document.addEventListener('pointercancel', pointerUp);
};

const attachResizeListener = (sizer, index, resize) => {
sizer.addEventListener('pointerdown', pointerDown(sizer, index, resize));
};

const createDom = (layout) => {
const { config, onResize } = layout;
const { children, id } = config;
Expand All @@ -64,9 +43,10 @@ const createDom = (layout) => {
const sizers = layoutDom.querySelectorAll(':scope > .sizer');
for(const [index, sizer] of Array.from(sizers).entries()){
sizer.id = Math.random().toString(16).replace('0.','');
attachResizeListener(sizer, index, onResize);
events.attachResizeListener(sizer, index, onResize);
}

events.attachDragListener();
return layoutDom;
};

Expand Down Expand Up @@ -105,3 +85,6 @@ class Layout {
};

export default Layout;

export const dragStart = events.dragStart;
export const onDrop = events.onDrop;
94 changes: 6 additions & 88 deletions test/editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,25 @@
flex-direction: column;
margin: 0;
}
.hidden { display: none; }
.tabs { height: 25px; background: #333; display: flex; }
.tab { padding: 5px 15px; cursor: pointer; }
.tab + .tab { margin-left: 1px; }
.editor { flex: 1; }
.drag-hover { background: #008062 !important; filter: hue-rotate(
294deg
) brightness(0.75) saturate(0.25);}
.dropped { background: blue; }
.mouse { position: absolute; bottom: 5px; right: 5px; }
iframe { border: 0; width: 100%; height: 100%; }
.active, .open { background: #1a1a1a; }
.drag-target {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #6698;
transition: left .3s, right .3s, top .3s, bottom .3s;
}
.right-hover { left: 50%; }
.left-hover { right: 50%; }
.bottom-hover { top: 50%; }
.top-hover { bottom: 50%; }
</style>

<body>
<div class="tabs"></div>
<div class="editor"></div>
<div class="mouse"></div>
<div class="drag-target hidden"></div>
</body>

<script>
<script type="module">
import { onDrop } from "https://unpkg.com/@fiug/layout@0.0.0-4";
//import { onDrop } from '../src/index.js';
const tabs = document.querySelector('.tabs');
const mouse = document.querySelector('.mouse');
const editor = document.querySelector('.editor');
const dragTarget = document.querySelector('.drag-target');
let hoverClassWait;

function hoverClassForSplit(x,y){
if(x < 0.25) return 'left-hover';
if(x > 0.75) return 'right-hover';
if(y < 0.25) return 'top-hover';
if(y > 0.75) return 'bottom-hover';
return '';
}
function removeHoverClasses(el){
el.classList.remove('left-hover');
el.classList.remove('right-hover');
el.classList.remove('top-hover');
el.classList.remove('bottom-hover');
}
let dragover;

function upsertTab(data){
Array.from(tabs.querySelectorAll('.tab.active'))
Expand All @@ -71,7 +36,6 @@
}
tabs.innerHTML += `<div class="tab active" file="${data}">${data}</div>`;
}

function openDoc({ name }){
upsertTab(name);
editor.innerHTML = `
Expand All @@ -81,53 +45,7 @@
editor.classList.add('open');
}

const dragover = (ev) => {
dragTarget.classList.remove('hidden');
ev.preventDefault();

const mousePercents = [
event.clientX/editor.clientWidth,
event.clientY/editor.clientHeight
];
mouse.innerHTML = mousePercents + hoverClassWait||'--';

if(!hoverClassWait){
hoverClassWait="inprogress";
setTimeout(() => {
if(hoverClassWait==="inprogress")
hoverClassWait = "done";
}, 500);
}
if(hoverClassWait==="inprogress") return;

const hoverClass = hoverClassForSplit(...mousePercents);
if(!hoverClass) removeHoverClasses(dragTarget);
if(hoverClass && !dragTarget.classList.contains(hoverClass)){
removeHoverClasses(dragTarget);
dragTarget.classList.add(hoverClass);
}
};
document.body.ondragover = editor.ondragover = dragover;
document.body.ondrop = (ev) => {
ev.preventDefault();
editor.classList.add('open');
//depending on hover class, will do different things here
const data = ev.dataTransfer.getData("text");
openDoc({ name: data });
//document.body.classList.remove('drag-hover');
dragTarget.classList.add('hidden');
mouse.innerHTML = '';
removeHoverClasses(dragTarget);
hoverClassWait = undefined;
};
dragTarget.ondragleave = (ev) => {
ev.preventDefault();
dragTarget.classList.add('hidden');
mouse.innerHTML = '';
removeHoverClasses(dragTarget);
hoverClassWait = undefined;
//document.body.classList.remove('drag-hover');
};

({ dragover } = onDrop(openDoc));
openDoc({ name: 'six.html' });

</script>
2 changes: 1 addition & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<body></body>

<script type="module">
import Layout from "https://unpkg.com/@fiug/layout@0.0.0-3";
import Layout from "https://unpkg.com/@fiug/layout@0.0.0-4";
//import Layout from "../src/index.js";

const layoutConfig = {
Expand Down
9 changes: 9 additions & 0 deletions test/terminal.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
<meta name="color-scheme" content="dark">
<div>terminal</div>
<pre class="term"></pre>
<script type="module">
import { onDrop } from "https://unpkg.com/@fiug/layout@0.0.0-4";
//import { onDrop } from '../src/index.js';
const term = document.querySelector('.term');
onDrop(({ name }) => {
term.textContent += (name + '\n');
});
</script>
Loading

0 comments on commit 08c36ec

Please sign in to comment.