当用户从下拉菜单中 Select 一个选项时,我正在try 将文本写入剪贴板.以下功能适用于除Safari之外的所有浏览器:

<select onChange="writeTextToClipboard(this.value);">
  <option value="Text I want to copy">Copy to clipboard</option>
</select>

function writeTextToClipboard(value) {
  navigator.clipboard.writeText(value);
}

我知道Safari希望将promise 传递给剪贴板对象的write函数,因此在this blog post之后,我修改了我的代码:

async function writeTextToClipboard(value) {
  // Safari, Chrome
  if(typeof ClipboardItem && navigator.clipboard.write) {
    const type = 'text/plain'
    const blob = new Blob([value], {type})
    const cbi = new ClipboardItem({[type]: blob})
    await navigator.clipboard.write([cbi])
    console.log(`Copied: ${value}`)
  }
  // Firefox
  else {
    navigator.clipboard.writeText(value);
  }
}

这仍然抛出了NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. Safari上,也打破了Chrome与NotAllowedError: Invalid Blob types.我错过了什么?

我在Safari 17.0上

UPDATES:

  • 我修复了Chrome上的这个问题,但仍然不能在Safari上运行.我创造了一个fiddle with a minimal example.
  • 我还意识到,当我的示例在按钮的onClick处理程序中调用,而不是在 Select 元素的onChange处理程序中调用时,它可以正常工作.我澄清了我的用例.
  • 目前我能想到的唯一解决方案是使用select元素以外的其他元素重新构建下拉菜单,并对其使用onClick事件处理程序,但如果可能的话,我想避免这种情况.
  • 这是asked before,但那篇文章中提到的解决方案使用的是execCommand(),这是不建议使用的,也不起作用.

推荐答案

为了让它在Safari中工作,它需要分两步进行:

  1. <select>中的值存储在隐藏的<input>
  2. 通过<button>将值从<input>复制到剪贴板:
const input = document.querySelector('input')

function store(value) {
  input.value = value
}

async function copy() {
  await navigator.clipboard.writeText(input.value)
  console.log(`Copied: ${input.value}`)
}
<select onchange="store(this.value)">
  <option value="">--Select your text--</option>
  <option value="Text 1">Text 1</option>
  <option value="Text 2">Text 2</option>
</select>
<input type="text" value="" hidden/>
<button onclick="copy()">Copy</button>

这应该适用于所有浏览器.如果你的设计目前确实有多余的空间来放置一个按钮,那就为它腾出空间.这是没有办法的.

Javascript相关问答推荐

为什么有些库公开了执行相同任务的方法,但每个方法都处于同步/同步上下文中?

除了在Angular 16中使用快照之外,什么是可行且更灵活的替代方案?

基于每个索引迭代嵌套对象

仅在React和JS中生成深色

根据总价格对航班优惠数组进行排序并检索前五个结果- Angular HTTP请求

我试图实现用户验证的reduxstore 和操作中出了什么问题?

为什么我的includes声明需要整个字符串?

GrapeJS -如何保存和加载自定义页面

从mat—country—select获取整个Country数组

判断表格单元格中是否存在文本框

Msgraph用户邀请自定义邮箱模板

我的服务工作器没有连接到我的Chrome扩展中的内容脚本.我该怎么解决这个问题?

引用在HTMLAttributes<;HTMLDivElement>;中不可用

Angular 订阅部分相互依赖并返回数组多个异步Http调用

不能将空字符串传递给cy.containes()

400 bad request error posting through node-fetch

Nextjs 13.4 Next-Auth 4.2登录(&Quot;凭据&,{});不工作

我想将Sitecore搜索面过滤器从多个转换为单个

在JS/TS中将复杂图形转换为数组或其他数据 struct

使用Java脚本替换字符串中的小文本格式hashtag