UNPKG

rabbit-design

Version:

A lightweight UI plugin library written in TypeScript and based on JavaScript

154 lines (120 loc) 4.77 kB
import { $el, bind, setCss, setHtml } from '../../dom-utils'; import { type, validComps } from '../../utils'; import PREFIX from '../prefix'; interface Config { onChange(elem: string, cb: ([status, $this]: [boolean, Element]) => void): void; } class Switch implements Config { readonly VERSION: string; readonly COMPONENTS: NodeListOf<Element>; constructor() { this.VERSION = '1.0'; this.COMPONENTS = $el('r-switch', { all: true }); this._create(this.COMPONENTS); } public onChange(elem: string, cb: ([status, $this]: [boolean, Element]) => void): void { const target = $el(elem); validComps(target, 'switch'); // 将当前选中的组件作为参数返回出去 const $this = target; bind(target, 'click', () => { const status = this._getStatus(target); type.isFn(cb, [status, $this]); }); } private _create(COMPONENTS: NodeListOf<Element>): void { COMPONENTS.forEach((node) => { this._init(node); this._handleChange(node, this._getStatus(node)); }); } private _init(node: Element): void { // 初始化按键切换索引 node.setAttribute('tabindex', '0'); // 初始化未选中状态的开关 if (node.getAttribute('checked') !== 'true') { node.setAttribute('checked', 'false'); } this._setStatusText(node, this._getStatus(node)); this._setStatusColor(node, this._getStatus(node)); } // 设置自定义的状态文本 private _setStatusText(node: Element, status: boolean): void { const { openText, closeText } = this._getStatusText(node); if (!openText || !closeText) return; // 创建文本容器 const TextBox = document.createElement('span'); TextBox.className = `${PREFIX.switch}-inner`; node.appendChild(TextBox); status ? setHtml(TextBox, openText) : setHtml(TextBox, closeText); } // 设置自定义的状态颜色 private _setStatusColor(node: any, status: boolean): void { const { trueColor, falseColor } = this._getColor(node); if (!trueColor || !falseColor) return; if (status) { setCss(node, 'borderColor', trueColor); setCss(node, 'backgroundColor', trueColor); } else { setCss(node, 'borderColor', falseColor); setCss(node, 'backgroundColor', falseColor); } } private _handleChange(node: Element, status: boolean): void { const ev_change = () => { if (this._isDisabled(node)) return false; if (this._isLoading(node)) return false; status ? (status = false) : (status = true); node.setAttribute('checked', `${status}`); const { openText, closeText } = this._getStatusText(node); this._changeStatusText(node, status, openText, closeText); this._setStatusColor(node, status); }; node.addEventListener('click', ev_change); } private _changeStatusText(node: Element, status: boolean, openText: any, closeText: any): void { // 获取当前开关下的文本容器 const TextBox = node.querySelector(`.${PREFIX.switch}-inner`); if (TextBox) { status ? setHtml(TextBox, openText) : setHtml(TextBox, closeText); } } private _getStatus(node: Element): boolean { // 转换为真实布尔类型 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return JSON.parse(node.getAttribute('checked')!); } private _isDisabled(node: Element): boolean { return ( node.getAttribute('disabled') === 'disabled' || node.getAttribute('disabled') === 'true' || node.getAttribute('disabled') === '' ); } private _isLoading(node: Element): boolean { return node.getAttribute('rb-loading') === 'true'; } private _getStatusText( node: Element ): { openText: string | null; closeText: string | null; } { return { openText: node.getAttribute('rb-open'), closeText: node.getAttribute('rb-close') }; } private _getColor( node: Element ): { trueColor: string | null; falseColor: string | null; } { return { trueColor: node.getAttribute('rb-true-color'), falseColor: node.getAttribute('rb-false-color') }; } } export default Switch;