124 lines
3.8 KiB
JavaScript
124 lines
3.8 KiB
JavaScript
import { create } from "./use_everywhere_utilities.js"
|
|
import { settingsCache } from "./use_everywhere_cache.js"
|
|
|
|
|
|
export class FloatingWindow extends HTMLElement {
|
|
constructor() {
|
|
super()
|
|
this.classList.add('ue_editor')
|
|
this.header = create('div', 'ue_editor_header', this)
|
|
this.body = create('div', 'ue_editor_body', this)
|
|
this.footer = create('button', 'ue_editor_footer', this, { innerText: "Close" })
|
|
|
|
/** @type {HTMLElement | null} */
|
|
this.firstFocusable = null
|
|
/** @type {HTMLElement | null} */
|
|
this.lastFocusable = null
|
|
|
|
this.header.addEventListener('mousedown',this.start_dragging.bind(this))
|
|
this.addEventListener('mousemove', this.mousemovedover.bind(this))
|
|
document.addEventListener('mousemove', this.mousemoved.bind(this))
|
|
document.addEventListener('mouseup',this.stop_dragging.bind(this))
|
|
document.addEventListener('mouseleave',this.stop_dragging.bind(this))
|
|
this.footer.addEventListener('click', this.hide.bind(this))
|
|
this.addEventListener("keydown", this.handle_keydown.bind(this));
|
|
|
|
this.dragging = false
|
|
this.hide()
|
|
document.body.append(this)
|
|
}
|
|
|
|
show() {
|
|
this.style.display = 'flex';
|
|
const tt = document.getElementById('ue_tooltip')
|
|
if (tt) tt.style.display = 'none'
|
|
this.showing = true
|
|
}
|
|
hide() {
|
|
this.style.display = 'none'
|
|
this.showing = false
|
|
}
|
|
set_title(title) {
|
|
this.header.innerText = title
|
|
}
|
|
set_body(element) {
|
|
this.body.innerHTML = ""
|
|
this.body.appendChild(element)
|
|
this.setup_focus_trap()
|
|
}
|
|
|
|
maybe_move_to(x,y) {
|
|
if (this.position && settingsCache.getSettingValue("Use Everywhere.Graphics.preserve edit window position")) return
|
|
this.move_to(x,y)
|
|
}
|
|
|
|
move_to(x,y) {
|
|
this.position = {x:x,y:y}
|
|
this.style.left = `${this.position.x}px`
|
|
this.style.top = `${this.position.y}px`
|
|
}
|
|
|
|
swallow(e) {
|
|
e.stopPropagation()
|
|
e.preventDefault()
|
|
}
|
|
|
|
start_dragging(e) {
|
|
this.dragging = true
|
|
this.swallow(e)
|
|
}
|
|
|
|
stop_dragging(e) {
|
|
this.dragging = false
|
|
}
|
|
|
|
mousemovedover(e) {
|
|
this.mousemoved(e)
|
|
this.swallow(e)
|
|
}
|
|
|
|
mousemoved(e) {
|
|
if (this.dragging) this.move_to( this.position.x + e.movementX , this.position.y + e.movementY )
|
|
}
|
|
|
|
/** @param {KeyboardEvent} e */
|
|
handle_keydown(e) {
|
|
if (e.key === "Escape" || e.key === "Enter") {
|
|
this.hide()
|
|
return
|
|
}
|
|
if (e.key === "Tab") {
|
|
if (e.shiftKey && document.activeElement === this.firstFocusable) {
|
|
this.lastFocusable.focus()
|
|
e.preventDefault()
|
|
return
|
|
}
|
|
if (!e.shiftKey && document.activeElement === this.lastFocusable) {
|
|
this.firstFocusable.focus()
|
|
e.preventDefault()
|
|
}
|
|
}
|
|
}
|
|
|
|
setup_focus_trap() {
|
|
this.firstFocusable = null
|
|
this.lastFocusable = null
|
|
|
|
const focusableEls = this.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])')
|
|
if (focusableEls?.length == 0) return
|
|
|
|
this.firstFocusable = focusableEls[0] ?? null
|
|
this.lastFocusable = focusableEls[focusableEls.length - 1] ?? null
|
|
|
|
if (this.firstFocusable) {
|
|
setTimeout(() => {
|
|
this.firstFocusable.focus()
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
customElements.define('ue-floating', FloatingWindow)
|
|
export const edit_window = new FloatingWindow()
|