229 lines
9.3 KiB
JavaScript
229 lines
9.3 KiB
JavaScript
let WINDOWS = {};
|
|
let MOUSE_MOVE_PROCESSING = {};
|
|
let globalIncrement = 1;
|
|
function escapeHTML(string) {
|
|
return string.replaceAll("&", "&").replaceAll("<", "<").replaceAll("\"", """);
|
|
}
|
|
function incrementZIndex(windowID, focus = false) {
|
|
WINDOWS[windowID].element.style.zIndex = String(globalIncrement);
|
|
WINDOWS[windowID].zIndex = globalIncrement;
|
|
globalIncrement++;
|
|
if (focus) {
|
|
WINDOWS[windowID].element.focus();
|
|
}
|
|
}
|
|
function createWindow(config) {
|
|
if (document.getElementById(config.id)) {
|
|
incrementZIndex(config.id);
|
|
return;
|
|
}
|
|
let _windowPaddingX = 1 * 2 + 10 * 2;
|
|
let _windowPaddingY = 1 * 2 + 10 * 2 + 35;
|
|
config.width = config.width || 600;
|
|
config.height = config.height || 400;
|
|
config.minWidth = config.minWidth || 200;
|
|
config.minHeight = config.minHeight || 200;
|
|
let realWidth = Math.max(config.minWidth, Math.min(config.width, innerWidth - _windowPaddingX - 20));
|
|
let realHeight = Math.max(config.minHeight, Math.min(config.height, innerHeight - _windowPaddingY - 20));
|
|
let posX = config.posX || Math.round((innerWidth / 2) - ((realWidth + _windowPaddingX) / 2));
|
|
let posY = config.posY || Math.round((innerHeight / 2) - ((realHeight + _windowPaddingY) / 2));
|
|
let wO = document.createElement("div");
|
|
wO.classList.add("window-outer");
|
|
let w = document.createElement("div");
|
|
w.classList.add("window");
|
|
w.style.width = `${realWidth}px`;
|
|
w.style.height = `${realHeight}px`;
|
|
w.innerHTML = config.content;
|
|
let wH = document.createElement("div");
|
|
wH.classList.add("window-header");
|
|
wH.innerHTML = `
|
|
<i class="window-header-button blank"></i>
|
|
<i class="window-header-button blank"></i>
|
|
<i class="window-header-button blank"></i>
|
|
<strong class="window-header-title">${config.title}</strong>
|
|
<i data-no-move class="window-header-button minimize"></i>
|
|
<i data-no-move class="window-header-button fullscreen"></i>
|
|
<i data-no-move class="window-header-button close"></i>
|
|
`;
|
|
let wC;
|
|
let wI = null;
|
|
if (config.typeable !== false) {
|
|
function syncInputs() {
|
|
setTimeout(function () {
|
|
let text = wI.value;
|
|
let cursor = wI.selectionStart;
|
|
let el = wC.querySelector("[data-type-area]");
|
|
if (!el) {
|
|
return;
|
|
}
|
|
if (cursor == text.length) {
|
|
el.innerHTML = `${escapeHTML(text)}<i class="cursor"> </i>`;
|
|
}
|
|
else {
|
|
el.innerHTML = `${escapeHTML(text.slice(0, cursor))}<span class="cursor">${escapeHTML(text[cursor])}</span>${escapeHTML(text.slice(cursor + 1))}`;
|
|
}
|
|
}, 1);
|
|
}
|
|
function setCursor() {
|
|
setTimeout(() => {
|
|
wI.setSelectionRange(wI.value.length, wI.value.length);
|
|
syncInputs();
|
|
}, 0);
|
|
}
|
|
wI = document.createElement("input");
|
|
wI.classList.add("window-input");
|
|
wI.id = `${config.id}__input`;
|
|
wI.oninput = (event) => {
|
|
syncInputs();
|
|
w.scrollTop = w.scrollHeight;
|
|
};
|
|
wI.onkeydown = (event) => {
|
|
if (event.key == "Enter") {
|
|
commandManager(config.id, wI.value.trim());
|
|
w.scrollTop = w.scrollHeight;
|
|
wI.value = "";
|
|
}
|
|
else {
|
|
syncInputs();
|
|
}
|
|
};
|
|
wI.onfocus = setCursor;
|
|
wI.onclick = setCursor;
|
|
wC = document.createElement("label");
|
|
wC.htmlFor = `${config.id}__input`;
|
|
}
|
|
else {
|
|
wC = document.createElement("div");
|
|
}
|
|
wC.classList.add("window-container");
|
|
wC.tabIndex = 0;
|
|
wC.style.left = `${posX}px`;
|
|
wC.style.top = `${posY}px`;
|
|
wC.id = config.id;
|
|
wC.style.zIndex = String(globalIncrement);
|
|
wC.style.width = `${realWidth + _windowPaddingX - 2}px`;
|
|
wO.append(w);
|
|
wC.append(wH, wO);
|
|
document.body.append(wC);
|
|
if (config.typeable !== false) {
|
|
wC.append(wI);
|
|
wI.focus();
|
|
}
|
|
else {
|
|
wC.focus();
|
|
}
|
|
WINDOWS[config.id] = {
|
|
element: wC,
|
|
height: realHeight,
|
|
width: realWidth,
|
|
posX: posX,
|
|
posY: posY,
|
|
fullscreen: false,
|
|
zIndex: globalIncrement,
|
|
vars: {}
|
|
};
|
|
function mouseMoveEvent(x, y) {
|
|
WINDOWS[config.id].posX = Math.max(0, Math.min(innerWidth - WINDOWS[config.id].width - _windowPaddingX, x - WINDOWS[config.id].vars.mouseOffsetX));
|
|
WINDOWS[config.id].posY = Math.max(0, Math.min(innerHeight - WINDOWS[config.id].height - _windowPaddingY, y - WINDOWS[config.id].vars.mouseOffsetY));
|
|
wC.style.left = `${WINDOWS[config.id].posX}px`;
|
|
wC.style.top = `${WINDOWS[config.id].posY}px`;
|
|
}
|
|
wC.addEventListener("focus", function () { incrementZIndex(config.id); });
|
|
for (const link of wC.querySelectorAll("a")) {
|
|
link.addEventListener("focus", function () { incrementZIndex(config.id); });
|
|
}
|
|
wH.addEventListener("mousedown", function (e) {
|
|
if (e.target.dataset.noMove !== undefined) {
|
|
return;
|
|
}
|
|
WINDOWS[config.id].vars.mouseOffsetX = e.clientX - WINDOWS[config.id].posX;
|
|
WINDOWS[config.id].vars.mouseOffsetY = e.clientY - WINDOWS[config.id].posY;
|
|
MOUSE_MOVE_PROCESSING[config.id] = {
|
|
callback: mouseMoveEvent,
|
|
mouseUp: true
|
|
};
|
|
});
|
|
wH.querySelector(".close").addEventListener("click", function () {
|
|
delete WINDOWS[config.id];
|
|
delete windowInformation[config.id];
|
|
delete MOUSE_MOVE_PROCESSING[config.id];
|
|
wC.remove();
|
|
if (typeof config.onDestroy === "function") {
|
|
config.onDestroy();
|
|
}
|
|
});
|
|
wH.querySelector(".fullscreen").addEventListener("click", function () {
|
|
if (WINDOWS[config.id].fullscreen) {
|
|
WINDOWS[config.id].posX = WINDOWS[config.id].vars.oldPosX;
|
|
WINDOWS[config.id].posY = WINDOWS[config.id].vars.oldPosY;
|
|
WINDOWS[config.id].width = WINDOWS[config.id].vars.oldWidth;
|
|
WINDOWS[config.id].height = WINDOWS[config.id].vars.oldHeight;
|
|
WINDOWS[config.id].fullscreen = false;
|
|
delete WINDOWS[config.id].vars.oldPosX;
|
|
delete WINDOWS[config.id].vars.oldPosY;
|
|
delete WINDOWS[config.id].vars.oldWidth;
|
|
delete WINDOWS[config.id].vars.oldHeight;
|
|
wC.style.left = `${WINDOWS[config.id].posX}px`;
|
|
wC.style.top = `${WINDOWS[config.id].posY}px`;
|
|
wC.style.width = `${WINDOWS[config.id].width + _windowPaddingX - 2}px`;
|
|
w.style.width = `${WINDOWS[config.id].width}px`;
|
|
w.style.height = `${WINDOWS[config.id].height}px`;
|
|
}
|
|
else {
|
|
WINDOWS[config.id].vars.oldPosX = WINDOWS[config.id].posX;
|
|
WINDOWS[config.id].vars.oldPosY = WINDOWS[config.id].posY;
|
|
WINDOWS[config.id].vars.oldWidth = WINDOWS[config.id].width;
|
|
WINDOWS[config.id].vars.oldHeight = WINDOWS[config.id].height;
|
|
WINDOWS[config.id].fullscreen = true;
|
|
WINDOWS[config.id].posX = 0;
|
|
WINDOWS[config.id].posY = 0;
|
|
WINDOWS[config.id].width = innerWidth;
|
|
WINDOWS[config.id].height = innerHeight;
|
|
wC.style.left = "0px";
|
|
wC.style.top = "0px";
|
|
wC.style.width = `${WINDOWS[config.id].width}px`;
|
|
w.style.width = `${WINDOWS[config.id].width - _windowPaddingX}px`;
|
|
w.style.height = `${WINDOWS[config.id].height - _windowPaddingY}px`;
|
|
}
|
|
});
|
|
globalIncrement++;
|
|
}
|
|
window.addEventListener("mousemove", function (e) {
|
|
for (const key of Object.keys(MOUSE_MOVE_PROCESSING)) {
|
|
MOUSE_MOVE_PROCESSING[key].callback(e.clientX, e.clientY);
|
|
}
|
|
});
|
|
window.addEventListener("mouseup", function () {
|
|
for (const key of Object.keys(MOUSE_MOVE_PROCESSING)) {
|
|
if (MOUSE_MOVE_PROCESSING[key].mouseUp) {
|
|
delete MOUSE_MOVE_PROCESSING[key];
|
|
}
|
|
;
|
|
}
|
|
});
|
|
function windowPreset(template) {
|
|
let el = document.querySelector(`#window-templates > [data-template-id="${template}"]`);
|
|
if (!el) {
|
|
return;
|
|
}
|
|
if (WINDOWS[template]) {
|
|
incrementZIndex(template, true);
|
|
return;
|
|
}
|
|
let config = {
|
|
id: template,
|
|
title: "~ - tSh",
|
|
content: "<div><b class=\"green\">trinkey@website</b>:<b class=\"blue\">~</b>$ <span data-type-area><i class=\"cursor\"> </i></span></div>"
|
|
};
|
|
for (const field of el.querySelectorAll("[data-template-field]")) {
|
|
config[field.dataset.templateField] = field.dataset.isNumber === "" ? +field.innerText : field.innerHTML;
|
|
}
|
|
createWindow(config);
|
|
for (const command of el.querySelectorAll("li")) {
|
|
WINDOWS[template].element.querySelector("[data-type-area]").innerHTML = command.innerHTML;
|
|
commandManager(template, command.innerHTML);
|
|
}
|
|
}
|
|
function copyButton() {
|
|
navigator.clipboard.writeText("<a href=\"https://trinkey.com/\" target=\"_blank\"><img src=\"https://trinkey.com/img/88x31.png\" alt=\"trinkey's 88x31. image of her cat on the right with the word 'trinkey' taking up the rest of the button.\" title=\"trinkey's 88x31. image of her cat on the right with the word 'trinkey' taking up the rest of the button.\"></a>");
|
|
}
|