Files
RomhackPlaza/resources/js/hovercard.js

130 lines
3.3 KiB
JavaScript
Raw Normal View History

/** @typedef { import('types/HovercardResponse.js').HovercardResponse} HovercardResponse */
export default function hovercard(){
return {
/**
* @type {boolean}
*/
start: false,
/**
* @type {HovercardResponse}
*/
data: null,
/**
* @type {boolean}
*/
loading: false,
/**
* @type {any}
*/
error: false,
/**
* @type {HTMLElement|null}
*/
anchorEl: null,
/**
* @type {number}
*/
x: 0,
/**
* @type {number}
*/
y: 0,
/**
*
* @param {HTMLElement} anchorEl
* @param {string} fetchUrl
* @return {Promise<void>}
*/
async open(anchorEl, fetchUrl){
if( this.start && this.anchorEl === anchorEl ){
// this.close();
return;
}
this.start = true;
this.anchorEl = anchorEl;
this.data = null;
this.loading = true;
this.error = false;
this.updatePosition(anchorEl);
try {
const RESPONSE = await fetch(fetchUrl);
if( !RESPONSE.ok )
throw new Error(RESPONSE.status);
let json = await RESPONSE.json();
if( !json.user )
throw new Error(RESPONSE.status);
this.data = json.user;
Alpine.nextTick(() => {
const card = document.querySelector('.hovercard');
if (card) window.refreshIcons(card);
this.updatePosition(this.anchorEl);
});
} catch( error ){
this.error = true;
} finally {
this.loading = false;
}
},
/**
* Update Hovercard position
* @param {HTMLElement} anchorEl
*/
updatePosition(anchorEl){
const RECT = anchorEl.getBoundingClientRect();
const SCROLL_X = window.scrollX;
const SCROLL_Y = window.scrollY;
const VIEWPORT_WIDTH = window.innerWidth;
const VIEWPORT_HEIGHT = window.innerHeight;
const CARD = document.querySelector('.hovercard');
const WIDTH = CARD?.offsetWidth || 280;
const HEIGHT = CARD?.offsetHeight || 320;
let x = RECT.right + SCROLL_X + 8;
let y = RECT.bottom + SCROLL_Y + 8;
if( x + WIDTH > VIEWPORT_WIDTH - 8 && RECT.left + SCROLL_X - WIDTH - 8 >= 8 ){
x = RECT.left + SCROLL_X - WIDTH - 8;
} else {
x = Math.max(8, Math.min(x, VIEWPORT_WIDTH - WIDTH - 8));
}
if( y + HEIGHT > VIEWPORT_HEIGHT + SCROLL_Y - 8 && RECT.top + SCROLL_Y - HEIGHT - 8 >= 8 ){
y = RECT.top + SCROLL_Y - HEIGHT - 8;
} else {
y = Math.max(8, Math.min(y, VIEWPORT_HEIGHT + SCROLL_Y - HEIGHT - 8));
}
this.x = x;
this.y = y;
},
/**
* Close the hovercard.
*/
close(){
this.start = false;
this.data = null;
this.anchorEl = null;
this.error = false;
}
}
}