zent
Version:
一套前端设计语言和基于React的实现
173 lines (172 loc) • 5.56 kB
JavaScript
import { addEventListener } from '../component/event-handler';
var map = new Map();
var createEvent = function (name) { return new Event(name, { bubbles: true }); };
function assign(ta) {
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta))
return;
var heightOffset = NaN;
var clientWidth = NaN;
var cachedHeight = NaN;
function init() {
var style = window.getComputedStyle(ta, null);
if (style.resize === 'vertical') {
ta.style.resize = 'none';
}
else if (style.resize === 'both') {
ta.style.resize = 'horizontal';
}
if (style.boxSizing === 'content-box') {
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
}
else {
heightOffset =
parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}
if (isNaN(heightOffset)) {
heightOffset = 0;
}
update();
}
function changeOverflow(value) {
{
var width = ta.style.width;
ta.style.width = '0px';
ta.offsetWidth;
ta.style.width = width;
}
ta.style.overflowY = value;
}
function getParentOverflows(el) {
var arr = [];
while (el && el.parentNode && el.parentNode instanceof Element) {
if (el.parentNode.scrollTop) {
arr.push({
node: el.parentNode,
scrollTop: el.parentNode.scrollTop,
});
}
el = el.parentNode;
}
return arr;
}
function resize() {
if (ta.scrollHeight === 0) {
return;
}
var overflows = getParentOverflows(ta);
var docTop = document.documentElement && document.documentElement.scrollTop;
ta.style.height = '';
ta.style.height = ta.scrollHeight + heightOffset + 'px';
clientWidth = ta.clientWidth;
overflows.forEach(function (el) {
el.node.scrollTop = el.scrollTop;
});
if (docTop) {
document.documentElement.scrollTop = docTop;
}
}
function update() {
resize();
var styleHeight = Math.round(parseFloat(ta.style.height));
var computed = window.getComputedStyle(ta, null);
var actualHeight = computed.boxSizing === 'content-box'
? Math.round(parseFloat(computed.height))
: ta.offsetHeight;
if (actualHeight < styleHeight) {
if (computed.overflowY === 'hidden') {
changeOverflow('scroll');
resize();
actualHeight =
computed.boxSizing === 'content-box'
? Math.round(parseFloat(window.getComputedStyle(ta, null).height))
: ta.offsetHeight;
}
}
else {
if (computed.overflowY !== 'hidden') {
changeOverflow('hidden');
resize();
actualHeight =
computed.boxSizing === 'content-box'
? Math.round(parseFloat(window.getComputedStyle(ta, null).height))
: ta.offsetHeight;
}
}
if (cachedHeight !== actualHeight) {
cachedHeight = actualHeight;
var evt = createEvent('autosize:resized');
try {
ta.dispatchEvent(evt);
}
catch (err) {
}
}
}
var pageResize = function () {
if (ta.clientWidth !== clientWidth) {
update();
}
};
var eventCancelList = [];
var destroy = (function (style) {
eventCancelList.forEach(function (unsubscribe) { return unsubscribe(); });
eventCancelList.splice(0, eventCancelList.length);
Object.keys(style).forEach(function (key) {
ta.style[key] = style[key];
});
map.delete(ta);
}).bind(ta, {
height: ta.style.height,
resize: ta.style.resize,
overflowY: ta.style.overflowY,
overflowX: ta.style.overflowX,
wordWrap: ta.style.wordWrap,
});
eventCancelList.push(addEventListener(ta, 'autosize:destroy', destroy));
if ('onpropertychange' in ta && 'oninput' in ta) {
eventCancelList.push(addEventListener(ta, 'keyup', update));
}
eventCancelList.push(addEventListener(window, 'resize', pageResize));
eventCancelList.push(addEventListener(ta, 'input', update));
eventCancelList.push(addEventListener(ta, 'autosize:update', update));
ta.style.overflowX = 'hidden';
ta.style.wordWrap = 'break-word';
map.set(ta, {
destroy: destroy,
update: update,
});
init();
}
function _destroy(ta) {
var methods = map.get(ta);
if (methods) {
methods.destroy();
}
}
function _update(ta) {
var methods = map.get(ta);
if (methods) {
methods.update();
}
}
function isNodeList(el) {
return 'length' in el;
}
export function autosize(el) {
if (el) {
Array.prototype.forEach.call(isNodeList(el) ? el : [el], function (x) { return assign(x); });
}
return el;
}
export function destroy(el) {
if (el) {
Array.prototype.forEach.call(isNodeList(el) ? el : [el], _destroy);
}
return el;
}
export function update(el) {
if (el) {
Array.prototype.forEach.call(isNodeList(el) ? el : [el], _update);
}
return el;
}