Vue directive - autosize
by joplomacedo
HTML
<div id="app">
<b-input v-autosize />
</div>
CSS
input {
font-size: 15px;
line-height: 1.5;
font-weight: 900;
padding: 1em;
}
Vue
function getStyle(el, prop) {
return el.currentStyle
? el.currentStyle[prop]
: window.getComputedStyle(el, null)[prop];
}
function setWidth(el, mimicEl) {
if ( el.lastRecordedValue === el.value ) return;
mimicEl.innerText = el.value;
el.style.width = mimicEl.offsetWidth + 10 + "px";
el.lastRecordedValue = el.value;
}
function normalizeOptions( options ) {
let defaults = {
minWidth: "none",
maxWidth: "none"
};
let normalizedOptions = { ...options };
if ( "min-width" in normalizedOptions ) {
normalizedOptions.minWidth = normalizedOptions['min-width'];
delete normalizedOptions["min-width"];
}
if ("max-width" in normalizedOptions) {
normalizedOptions.maxWidth = normalizedOptions["max-width"];
delete normalizedOptions["max-width"];
}
return {
...defaults,
...normalizedOptions
};
}
const autoSizeDirective = {
inserted(el, binding) {
let inputEl;
if (el.nodeName == "INPUT") {
inputEl = el;
} else {
inputEl = el.querySelector("input");
if (!inputEl) {
return false;
}
}
const options = normalizeOptions(binding.value);
inputEl.style.boxSizing = "content-box";
inputEl.style.minWidth = options.minWidth;
inputEl.style.maxWidth = options.maxWidth;
const mimicEl = document.createElement("div");
mimicEl.style.display = "inline-block";
mimicEl.style.font = getStyle(inputEl, "font");
mimicEl.style.textTransform = getStyle(inputEl, "text-transform");
mimicEl.style.letterSpacing = getStyle(inputEl, "letter-spacing");
inputEl.addEventListener("keydown", function() {
setTimeout(setWidth.bind(null, inputEl, mimicEl));
});
inputEl.addEventListener('change', function ( ) {
setWidth(inputEl, mimicEl);
});
el.theMimicEl = mimicEl;
document.body.appendChild(mimicEl);
setWidth(inputEl,...