@mdui/jq
Version:
拥有和 jQuery 相似 API 的轻量级 JavaScript 工具库
132 lines (131 loc) • 4.78 kB
JavaScript
import { getDocument } from 'ssr-window';
import { $ } from '../$.js';
import { isBorderBox, getExtraWidth, getComputedStyleValue, } from '../shared/css.js';
import { isBoolean, isString, isDocument, isFunction, isWindow, toElement, eachArray, } from '../shared/helper.js';
import './css.js';
import './each.js';
/**
* 值上面的 padding、border、margin 处理
* @param element
* @param name
* @param value
* @param funcIndex
* @param includeMargin
* @param multiply
*/
const handleExtraWidth = (element, name, value, funcIndex, includeMargin, multiply) => {
// 获取元素的 padding, border, margin 宽度(两侧宽度的和)
const getExtraWidthValue = (extra) => {
return (getExtraWidth(element, name.toLowerCase(), extra) *
multiply);
};
if (funcIndex === 2 && includeMargin) {
value += getExtraWidthValue('margin');
}
if (isBorderBox(element)) {
if (funcIndex === 0) {
value -= getExtraWidthValue('border');
}
if (funcIndex === 1) {
value -= getExtraWidthValue('border');
value -= getExtraWidthValue('padding');
}
}
else {
if (funcIndex === 0) {
value += getExtraWidthValue('padding');
}
if (funcIndex === 2) {
value += getExtraWidthValue('border');
value += getExtraWidthValue('padding');
}
}
return value;
};
/**
* 获取元素的样式值
* @param element
* @param name
* @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
* @param includeMargin
*/
const get = (element, name, funcIndex, includeMargin) => {
const document = getDocument();
const clientProp = `client${name}`;
const scrollProp = `scroll${name}`;
const offsetProp = `offset${name}`;
const innerProp = `inner${name}`;
// $(window).width()
if (isWindow(element)) {
// outerWidth, outerHeight 需要包含滚动条的宽度
return funcIndex === 2
? element[innerProp]
: toElement(document)[clientProp];
}
// $(document).width()
if (isDocument(element)) {
const doc = toElement(element);
return Math.max(
// @ts-ignore
element.body[scrollProp], doc[scrollProp],
// @ts-ignore
element.body[offsetProp], doc[offsetProp], doc[clientProp]);
}
const value = parseFloat(getComputedStyleValue(element, name.toLowerCase()) || '0');
return handleExtraWidth(element, name, value, funcIndex, includeMargin, 1);
};
/**
* 设置元素的样式值
* @param element
* @param elementIndex
* @param name
* @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
* @param includeMargin
* @param value
*/
const set = (element, elementIndex, name, funcIndex, includeMargin, value) => {
let computedValue = isFunction(value)
? value.call(element, elementIndex, get(element, name, funcIndex, includeMargin))
: value;
if (computedValue == null) {
return;
}
const $element = $(element);
const dimension = name.toLowerCase();
// 特殊的值,不需要计算 padding、border、margin
if (isString(computedValue) &&
['auto', 'inherit', ''].includes(computedValue)) {
$element.css(dimension, computedValue);
return;
}
// 其他值保留原始单位。注意:如果不使用 px 作为单位,则算出的值一般是不准确的
const suffix = computedValue.toString().replace(/\b[0-9.]*/, '');
const numerical = parseFloat(computedValue);
computedValue =
handleExtraWidth(element, name, numerical, funcIndex, includeMargin, -1) +
(suffix || 'px');
$element.css(dimension, computedValue);
};
eachArray(['Width', 'Height'], (name) => {
eachArray([`inner${name}`, name.toLowerCase(), `outer${name}`], (funcName, funcIndex) => {
$.fn[funcName] = function (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
margin,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value) {
// 是否是赋值操作
const isSet = arguments.length && (funcIndex < 2 || !isBoolean(margin));
const includeMargin = margin === true || value === true;
// 获取第一个元素的值
if (!isSet) {
return this.length
? get(this[0], name, funcIndex, includeMargin)
: undefined;
}
// 设置每个元素的值
return this.each((index, element) => {
return set(element, index, name, funcIndex, includeMargin, margin);
});
};
});
});