UNPKG

ph-utils

Version:

js 开发工具集,前后端都可以使用(commonjs和es module)

102 lines (101 loc) 3.22 kB
/** * 创建一个临时节点缓存待复制数据 * @param {String} value - 待复制文本 * @return {HTMLElement} */ function createFakeElement(value) { const fakeElement = document.createElement("textarea"); fakeElement.style.border = "0"; fakeElement.style.padding = "0"; fakeElement.style.margin = "0"; fakeElement.style.position = "absolute"; fakeElement.style.left = "-9999px"; fakeElement.style.top = "-9999"; fakeElement.setAttribute("readonly", ""); fakeElement.value = value; return fakeElement; } /** 通过执行 execCommand 来执行复制 */ function copyFromCommand(text) { // 添加节点 const fakeEl = createFakeElement(text); document.body.append(fakeEl); fakeEl.focus(); fakeEl.select(); // 执行复制 const res = document.execCommand("copy"); fakeEl.remove(); // 删除节点 return Promise.resolve(res); } /** 使用 navigator.clipboard 复制 */ function copyFromClipboard(text) { const theClipboard = navigator.clipboard; if (theClipboard != null) { return theClipboard .writeText(text) .then(() => { Promise.resolve(true); }) .catch(() => Promise.resolve(false)); } return Promise.resolve(false); } /** 解析待复制的文本 */ function parseCopyText(source) { let copyText = null; // 待复制文本 let sourceEl = null; // 获取待复制数据 if (typeof source === "string") { // 从节点拿数据 if (source.startsWith("#") || source.startsWith(".")) { sourceEl = document.querySelector(source); if (sourceEl == null) { copyText = source; } } else { copyText = source; } } if (source instanceof HTMLElement) { sourceEl = source; } // 从节点获取待复制数据 if (sourceEl != null) { if (sourceEl.hasAttribute("data-copy-text")) { copyText = sourceEl.getAttribute("data-copy-text"); } else { const tagName = sourceEl.tagName; if (tagName === "INPUT" || tagName === "TEXTAREA") { copyText = sourceEl.value; } else { copyText = sourceEl.textContent; } } } return copyText; } /** * 复制数据, 可以从多种类型的数据 * 1. 直接复制文本: await copy("待复制的文本") * 2. 复制节点上的 data-copy-text: * <button data-copy-text="这是待复制的文本">复制</button> * await copy(e.target) // or await copy("#a") or await copy(document.querySelector('#a')) * 3. 直接复制节点本身数据: await copy('#a') * @param {string | HTMLElement} source 复制源, 从中解析待复制的数据 * @returns {Promise<boolean>} 是否复制成功 */ export async function copy(source) { // 待复制文本 const copyText = parseCopyText(source); if (copyText == null) { return Promise.resolve(false); } const v = await copyFromClipboard(copyText); if (v === false) { return copyFromCommand(copyText); } return Promise.resolve(true); }