🏠 

FloatingWindow

Adds FloatingWindow

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/477480/1270124/FloatingWindow.js

// ==UserScript==
// @name             FloatingWindow
// @version          1.2
// @grant            GM_addStyle
// @grant            GM_getValue
// @grant            GM_setValue
// @description Adds FloatingWindow
// ==/UserScript==
GM_addStyle(`
.floatingWindowContainer {
width:200px;
position:fixed;
opacity:0.5;
z-index: 9999;
}
.floatingWindowTitleBar {
background-color:#fff;
font-weight:bold;
text-align:center;
cursor:pointer;
}
.floatingWindowContainer.active {
opacity:1;
z-index: 10000;
}
.floatingWindowBody{
flex-wrap:wrap;
}
`);
class FloatingWindow {
constructor(title,settings = {}) {
this.settings = {
position:settings?.position || {x:window.innerWidth*0.8,y:100},
open: settings.hasOwnProperty("open") ? settings.open : true,
bodyDisplay:settings?.bodyDisplay || "block"
}
this.container = document.createElement("div");
this.container.className = "floatingWindowContainer";
this.container.id = title.toLowerCase().replaceAll(/\W+/g,"_");
this.windowPosition = GM_getValue(`${this.container.id}_position`,this.settings.position);
this.container.style.left = `${this.windowPosition.x}px`;
this.container.style.top = `${this.windowPosition.y}px`;
this.titleBar = document.createElement("div");
this.titleBar.className = "floatingWindowTitleBar";
this.titleBar.appendChild(document.createTextNode(title));
this.titleBar.addEventListener("pointerdown",(e)=>{this.pointerDownHandler(e);});
document.addEventListener("pointermove",(e)=>{this.pointerMoveHandler(e);});
document.addEventListener("pointerup",(e)=>{this.pointerUpHandler(e);});
this.container.appendChild(this.titleBar);
this.body = document.createElement("div");
this.body.className = "floatingWindowBody";
this.windowOpen = GM_getValue(`${this.container.id}_open`,this.settings.open);
if (this.windowOpen) this.container.classList.add("active");
this.body.style.display = this.windowOpen ? this.settings.bodyDisplay : "none";
this.container.appendChild(this.body);
document.body.appendChild(this.container);
this.pointerValues = {
newPosition:null,
positionOffset:null,
dragging:false
};
}
toggleWindow() {
this.windowOpen = !this.windowOpen;
this.container.classList.toggle("active");
GM_setValue(`${this.container.id}_open`,this.windowOpen);
this.body.style.display = this.windowOpen ? this.settings.bodyDisplay : "none";
}
pointerDownHandler(e) {
this.pointerValues.positionOffset = {
x:e.clientX - this.windowPosition.x,
y:e.clientY - this.windowPosition.y
};
}
pointerMoveHandler(e) {
if (this.pointerValues.positionOffset) {
e.preventDefault()
this.pointerValues.newPosition = {
x:e.clientX - this.pointerValues.positionOffset.x,
y:e.clientY - this.pointerValues.positionOffset.y
};
if (!this.pointerValues.dragging) {
if (
Math.abs(e.clientX - this.windowPosition.x) > 10 ||
Math.abs(e.clientY - this.windowPosition.y) > 10
) this.pointerValues.dragging = true;
} else {
this.container.style.left = `${this.pointerValues.newPosition.x}px`;
this.container.style.top = `${this.pointerValues.newPosition.y}px`;
}
}
}
pointerUpHandler(e) {
if (this.pointerValues.positionOffset) {
if (this.pointerValues.dragging) {
this.pointerValues.newPosition = {
x:e.clientX - this.pointerValues.positionOffset.x,
y:e.clientY - this.pointerValues.positionOffset.y
};
this.container.style.left = `${this.pointerValues.newPosition.x}px`;
this.container.style.top = `${this.pointerValues.newPosition.y}px`;
this.windowPosition = this.pointerValues.newPosition;
GM_setValue(`${this.container.id}_position`,this.windowPosition);
} else {
this.toggleWindow();
}
this.pointerValues.dragging = false;
this.pointerValues.newPosition = this.pointerValues.positionOffset = null;
}
}
}