vybe/client/space.js

143 lines
3.2 KiB
JavaScript
Raw Normal View History

2024-04-15 14:27:21 -07:00
let space;
2024-04-15 21:52:21 -07:00
let spaceId;
2024-03-18 23:07:48 -07:00
let scale = 1;
let editing;
let dragging;
let moved;
let offset;
function mousemove(event) {
let left = (event.clientX - space.offsetLeft) * scale - offset.x;
let top = (event.clientY - space.offsetTop) * scale - offset.y;
dragging.style.left = `${left < 0 ? 0 : left}px`;
dragging.style.top = `${top < 0 ? 0 : top}px`;
moved = true;
2024-04-15 14:27:21 -07:00
save(dragging);
2024-03-18 23:07:48 -07:00
}
2024-04-15 14:27:21 -07:00
function save(span) {
window.emit('save_span', {
2024-04-15 21:52:21 -07:00
thread: spaceId,
2024-04-15 14:27:21 -07:00
id: span.id ? span.id.slice(4) : '',
content: span.innerText,
x: span.style.left.slice(0, -2),
y: span.style.top.slice(0, -2),
scale: span.scale
}, msg => {
2024-04-15 21:52:21 -07:00
if (!msg.success)
console.log('span save failed: ' + msg.message);
2024-04-15 14:27:21 -07:00
if (!span.id)
span.id = 'span' + msg.id;
});
2024-03-18 23:07:48 -07:00
}
2024-04-15 22:23:14 -07:00
function add(s) {
2024-03-18 23:07:48 -07:00
let span = document.createElement('span');
span.classList.add('span');
2024-04-15 22:23:14 -07:00
if (s.id)
span.id = 'span' + s.id;
span.innerText = s.content;
2024-03-18 23:07:48 -07:00
span.contentEditable = true;
span.spellcheck = false;
2024-04-15 22:23:14 -07:00
span.scale = s.scale;
span.style.left = `${s.x}px`;
span.style.top = `${s.y}px`;
span.style.transform = `translate(-50%, -50%) scale(${s.scale})`;
2024-03-18 23:07:48 -07:00
span.onkeydown = function(event) {
if (event.key === 'Enter' && !event.getModifierState('Shift')) {
event.preventDefault();
editing = null;
span.blur();
}
};
span.oninput = function(event) {
2024-04-15 14:27:21 -07:00
save(this);
2024-03-18 23:07:48 -07:00
};
span.onblur = function(event) {
2024-04-15 14:27:21 -07:00
if (this.innerText)
return;
save(this);
this.remove();
2024-03-18 23:07:48 -07:00
};
span.onwheel = function(event) {
event.preventDefault();
this.scale *= 1 - event.deltaY * .001;
this.style.transform = `translate(-50%, -50%) scale(${this.scale})`;
2024-04-15 21:52:21 -07:00
save(this);
2024-03-18 23:07:48 -07:00
};
span.onmousedown = function(event) {
if (dragging || editing === this)
return;
dragging = this;
event.preventDefault();
offset = {
x: event.clientX - (space.offsetLeft + this.offsetLeft),
y: event.clientY - (space.offsetTop + this.offsetTop)
};
moved = false;
document.addEventListener('mousemove', mousemove);
};
span.onmouseup = function(event) {
event.stopPropagation();
document.removeEventListener('mousemove', mousemove);
dragging = null;
if (moved)
return;
this.focus();
editing = this;
};
space.append(span);
return span;
}
2024-04-15 22:23:14 -07:00
window.socket.on('span', msg => {
if (msg.thread !== spaceId)
return;
let span = document.getElementById('span' + msg.id);
if (span) {
span.innerText = msg.content;
span.x = msg.x;
span.y = msg.y;
span.scale = msg.scale;
span.style.transform = `translate(-50%, -50%) scale(${msg.scale})`;
}
else
add(msg);
});
2024-04-15 14:27:21 -07:00
export default function loadSpace() {
if (!space) {
space = document.getElementById('space');
space.onmouseup = event => {
if (dragging) {
dragging.onmouseup(event);
return;
}
if (editing) {
if (event.target !== editing)
editing = null;
return;
}
2024-04-15 22:23:14 -07:00
editing = add({
x: event.offsetX + space.scrollLeft,
y: event.offsetY + space.scrollTop,
scale: 1,
content: ''
});
2024-04-15 14:27:21 -07:00
editing.focus();
};
2024-03-18 23:07:48 -07:00
}
2024-04-15 21:52:21 -07:00
if (spaceId === window.threadId)
2024-03-18 23:07:48 -07:00
return;
2024-04-15 21:52:21 -07:00
spaceId = window.threadId;
2024-04-15 14:27:21 -07:00
space.innerHTML = '';
2024-04-15 21:52:21 -07:00
window.emit('get_space', { thread: window.threadId }, msg => {
if (!msg.success)
console.log('get space failed: ' + msg.message);
2024-04-15 22:23:14 -07:00
for (const span of msg.spans)
add(span);
2024-04-15 14:27:21 -07:00
});
2024-03-18 23:07:48 -07:00
};