UNPKG

@scidian/osui

Version:

Lightweight JavaScript UI library.

160 lines (140 loc) 6.58 kB
// VARIABLES // getVariable() Gets a CSS variable by name, hyphens optional // setVariable() Sets a CSS variable by name, hyphens optional // FONT / GUI SIZING // baseSize() // fontSize() // guiScale() Calculates current GUI scale based on <body> font size // FONT METRICS // getTextWidth() Gets the width of a string in pixels // getFontCssFromElement() // HTML ELEMENTS // parentElementWithCSS Finds and returns parent of 'element' with a specific CSS key, value // SIZE PARSING // parseSize() // toEm() Returns input units from 'px' to 'em' // toPx() Returns input units to converted pixels string ending in 'px' class Css { /******************** VARIABLES ********************/ /** Gets a CSS variable by name, hyphens optional */ static getVariable(variable, element) { variable = String(variable); if (!variable.startsWith('--')) variable = '--' + variable; if (element && element.isElement) element = element.dom; if (!element || !(element instanceof HTMLElement)) { element = document.querySelector(':root'); } return getComputedStyle(element).getPropertyValue(variable); } /** * Sets a CSS variable by name * * @param {*} variable variable name, first two hypens optional * @param {*} valueAsString new css variable value as string * @param {*} element Optional, will apply to 'root' element if not defined */ static setVariable(variable, valueAsString, element) { variable = String(variable); if (!variable.startsWith('--')) variable = '--' + variable; if (element && element.isElement) element = element.dom; if (!element || !(element instanceof HTMLElement)) { element = document.querySelector(':root'); } element.style.setProperty(variable, valueAsString); } /******************** FONT / GUI SIZING ********************/ static baseSize() { /* 1rem === 10px @ root */ return parseFloat(getComputedStyle(document.querySelector(':root')).fontSize); } static fontSize(element = document.body) { return parseFloat(getComputedStyle(element).fontSize); } /** Calculates current GUI scale based on <body> font size */ static guiScale(element = document.body) { return Css.fontSize(element) / Css.baseSize(); } /******************** FONT METRICS ********************/ /* Gets the width of a string in pixels, use with getFontCssFromElement() */ static getTextWidth(text, font) { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); ctx.font = font; return ctx.measureText(text).width; } static getFontCssFromElement(element = document.body) { const fontWeight = getComputedStyle(element).fontWeight || 'normal'; const fontSize = getComputedStyle(element).fontSize || '16px'; const fontFamily = getComputedStyle(element).fontFamily || 'Arial'; return `${fontWeight} ${fontSize} ${fontFamily}`; } /******************** HTML ELEMENTS ********************/ /** Finds and returns parent of 'element' with a specific CSS key, value */ static parentElementWithCSS(element, cssKey, cssValueOrArrayOfPossibleValues) { const values = (Array.isArray(cssValueOrArrayOfPossibleValues)) ? cssValueOrArrayOfPossibleValues : [ cssValueOrArrayOfPossibleValues ]; cssKey = cssKey.replace(/([A-Z])/g, "-$1").toLowerCase(); // sanitize key if (element.isElement && element.dom) element = element.dom; let parent = element.parentElement; while (parent) { const defaultView = (parent.ownerDocument || document).defaultView; const computed = defaultView.getComputedStyle(parent, null); const property = computed.getPropertyValue(cssKey); if (property) { for (let i = 0; i < values.length; i++) { const cssValue = values[i]; if (property == cssValue) return parent; } } parent = parent.parentElement; } return undefined; } /******************** SIZE PARSING ********************/ static parseSize(size) { if (typeof size === 'string') { if (size.includes('%') || size.includes('px') || size.includes('em') || size.includes('rem') || size.includes('ch') || size.includes('ex') || size.includes('cap') || size.includes('vw') || size.includes('vh') || size.includes('vmin') || size.includes('vmax')) { return size; } else { return parseInt(size) + 'px'; } } else { return parseInt(size) + 'px'; } } /** Returns input units from 'px' to 'em' */ static toEm(pixels, element = document.body) { const parsedSize = Css.parseSize(pixels); if (parsedSize.includes('px')) { return ((parseFloat(parsedSize) / 10.0) / Css.guiScale(element)) + 'em'; } else if (parsedSize.includes('em')) { return parsedSize; } console.warn(`Css.toEm: Could not convert to em, unit passed in: ${pixels}`); return size; } /** Returns input units to converted pixels string ending in 'px' */ static toPx(size, element = document.body, dimension = 'w' /* or 'h' (for percentage) */) { const parsedSize = Css.parseSize(size); if (parsedSize.includes('%')) { if (element) { const parent = Css.parentElementWithCSS(element, 'position', [ 'relative', 'absolute' ]); if (parent) { if (dimension === 'w') return (parseFloat(size) * 0.01 * parent.offsetWidth) + 'px'; else return (parseFloat(size) * 0.01 * parent.offsetHeight) + 'px'; } } } else if (parsedSize.includes('px')) { return parsedSize; } else if (parsedSize.includes('rem')) { return parseInt((parseFloat(size) * 10.0)) + 'px'; } else if (parsedSize.includes('em')) { return parseInt((parseFloat(size) * 10.0 * Css.guiScale(element))) + 'px'; } console.warn(`Css.toPx: Could not convert to pixels, unit passed in: ${size}`); return parseInt(parsedSize) + 'px'; } } export { Css };