From 325d9571ece37018065a91f8b6c4b4d543d7ee50 Mon Sep 17 00:00:00 2001 From: * <8> Date: Wed, 22 Dec 2021 20:03:34 +0800 Subject: [PATCH] Match-id-73c0fd446aab80ee0e351fda1a6d575656e751f4 --- libs/horizon/src/dom/utils/Common.ts | 75 ++++++++++++++++++++++++ libs/horizon/src/dom/utils/DomCreator.ts | 25 ++++++++ libs/horizon/src/dom/utils/Interface.ts | 9 +++ 3 files changed, 109 insertions(+) create mode 100644 libs/horizon/src/dom/utils/Common.ts create mode 100644 libs/horizon/src/dom/utils/DomCreator.ts create mode 100644 libs/horizon/src/dom/utils/Interface.ts diff --git a/libs/horizon/src/dom/utils/Common.ts b/libs/horizon/src/dom/utils/Common.ts new file mode 100644 index 00000000..771105bb --- /dev/null +++ b/libs/horizon/src/dom/utils/Common.ts @@ -0,0 +1,75 @@ +import {HorizonDom} from './Interface'; + +/** + * 获取当前聚焦的 input 或者 textarea 元素 + * @param currentDoc 指定 document + */ +export function getFocusedDom(currentDoc?: Document): HorizonDom | void { + let currentDocument; + if (currentDoc) { + currentDocument = currentDoc; + } else { + if (document) { + currentDocument = document; + } + } + if (!currentDocument) { + return null; + } else if (currentDocument.activeElement) { + return currentDocument.activeElement; + } else { + return currentDocument.body; + } +} + +// 如果 input 或者 textarea 元素中有文字被选中时,activeElement 属性就会返回该元素 +// 此处是为了返回深层的 iframe 中的真实元素 +export function getIFrameFocusedDom() { + const currentWindow = window; + let focusedDom = getFocusedDom(); + // 深度优先,返回的元素如果是 iframe 对象则继续查找 + while (focusedDom instanceof currentWindow.HTMLIFrameElement) { + try { + // 访问 HTMLIframeElement 的 contentDocument 可能会导致浏览器抛出错误 + if (typeof focusedDom.contentWindow.location.href === 'string') { // iframe 的内容为同源 + focusedDom = getFocusedDom(focusedDom.contentWindow.document); + } else { // 非同源 iframe 因为安全性原因无法获取其中的具体元素 + break; + } + } catch (e) { // 非同源 iframe 因为安全性原因无法获取其中的具体元素 + break; + } + } + return focusedDom; +} + +export function isElement(dom) { + return dom.nodeType === 1; +} + +export function isText(dom) { + return dom.nodeType === 3; +} + +export function isComment(dom) { + return dom.nodeType === 8; +} + +export function isDocument(dom) { + return dom.nodeType === 9; +} + +export function isDocumentFragment(dom) { + return dom.nodeType === 11; +} + +export function getRootElement(dom: HorizonDom): HorizonDom { + let rootElement = dom; + + while (rootElement.parentNode) { + // @ts-ignore + rootElement = rootElement.parentNode; + } + + return rootElement; +} diff --git a/libs/horizon/src/dom/utils/DomCreator.ts b/libs/horizon/src/dom/utils/DomCreator.ts new file mode 100644 index 00000000..ee3aa387 --- /dev/null +++ b/libs/horizon/src/dom/utils/DomCreator.ts @@ -0,0 +1,25 @@ + +export const NSS = { + html: 'http://www.w3.org/1999/xhtml', + math: 'http://www.w3.org/1998/Math/MathML', + svg: 'http://www.w3.org/2000/svg', +}; + +// 创建DOM元素 +export function createDom( + tagName: string, + props: Object, + parentNamespace: string, +): Element { + let dom: Element; + const selfNamespace = NSS[tagName] || NSS.html; + const ns = parentNamespace !== NSS.html ? parentNamespace : selfNamespace; + + if (ns !== NSS.html) { + dom = document.createElementNS(ns, tagName); + } else { + dom = document.createElement(tagName); + } + + return dom; +} diff --git a/libs/horizon/src/dom/utils/Interface.ts b/libs/horizon/src/dom/utils/Interface.ts new file mode 100644 index 00000000..62887f72 --- /dev/null +++ b/libs/horizon/src/dom/utils/Interface.ts @@ -0,0 +1,9 @@ +export interface IProperty { + [propName: string]: any +} + +export interface HorizonSelect extends HTMLSelectElement { + _multiple: boolean; +} + +export type HorizonDom = Element | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;