✨elem.showNote()
🔰 JS ⟩ browser ⟩ DOM ⟩ types ⟩ Element ⟩ bounding rect ⟩ elem.showNote()
💾 replit: elem.showNote() - show note beside element.
const { log } = console;
// ⭐️ select element
function $(selector, parent = document) {
return parent.querySelector(selector);
}
// ⭐️ newElement()
/*
* create and configure a new Element
*
* @param {string} tagName - like 'div', 'span' ...
* @param {function} config - function to configure the newly created element
* @return {Element}
*/
function newElement(tagName, config) {
let elem = document.createElement(tagName);
if (config) { config(elem) }
return elem;
}
// ------------- extending Element -------------
// 🔸 elem.anchorPositionFor()
/*
* calculate the "anchor" point for the "note" element
*
* @param {Element} noteElem - the "note" element to be put aside
* @param {string} position - top | right | bottom (default)
* @return {object} - x, y coords relative to viewport
*
* 🧨 warning:
* two elements (`this` and `noteElem`) must be in the document
* before calling `getBoundingClientRect()`❗
*/
Element.prototype.anchorPositionFor = function(noteElem, position = 'bottom') {
const { x: x1, y: y1, width: w1, height: h1 } = this.getBoundingClientRect();
const { width: w2, height: h2 } = noteElem.getBoundingClientRect();
switch (position) {
case 'top' : return { x: x1 , y: y1 - h2 };
case 'right' : return { x: x1 + w1, y: y1 };
case 'bottom': return { x: x1 , y: y1 + h1 };
default: return { x: x1, y: y1 + h1 }; // default = 'bottom'
}
};
// 🔸 elem.showNote()
Element.prototype.showNote = function(html, position='bottom') {
const _ = newElement('div', (elem)=>{
elem.innerHTML = html;
elem.classList.add('note');
// ⭐ must add to DOM before getting its bounding rect
document.body.append(elem);
const {x, y} = this.anchorPositionFor(elem, position);
elem.style.left = x + 'px';
elem.style.top = y + 'px';
});
};
// ------------- main -------------
const info = $('#scrollInfo');
$('#span1').showNote('hello world', 'top');
$('#span2').showNote('hello world');
// scroll handler
window.onscroll = (event) => {
info.innerText = `scrollX: ${scrollX}, scrollY: ${scrollY}`;
};
// ------------- class Vector (not used) -------------
class Vector {
// init
constructor(x, y) {
this.x = x;
this.y = y;
}
// u.add(v): u + v
add(v) {
return new Vector(this.x + v.x, this.y + v.y)
}
// u.inverse(): -u
inverse() {
return new Vector(-this.x, -this.y);
}
// u.minus(v): u - v
minus(v) {
return this.add(v.inverse());
}
// toString
toString() {
return `(${this.x}, ${this.y})`
}
}
Last updated