1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-18 05:01:17 +02:00

Set clipboard data programmitcally on copy when supported (#1815)

This commit is contained in:
Tobias Andersen
2018-05-11 04:45:40 +02:00
committed by Ian Storm Taylor
parent 0cfd54fc19
commit 62d87b23c0

View File

@@ -1,10 +1,13 @@
import Base64 from 'slate-base64-serializer' import Base64 from 'slate-base64-serializer'
import { IS_CHROME, IS_SAFARI, IS_OPERA } from 'slate-dev-environment' import { IS_CHROME, IS_SAFARI, IS_OPERA } from 'slate-dev-environment'
import TRANSFER_TYPES from '../constants/transfer-types'
import getWindow from 'get-window' import getWindow from 'get-window'
import findDOMNode from './find-dom-node' import findDOMNode from './find-dom-node'
import { ZERO_WIDTH_SELECTOR, ZERO_WIDTH_ATTRIBUTE } from './find-point'
import removeAllRanges from './remove-all-ranges' import removeAllRanges from './remove-all-ranges'
import { ZERO_WIDTH_SELECTOR, ZERO_WIDTH_ATTRIBUTE } from './find-point'
const { FRAGMENT, HTML, TEXT } = TRANSFER_TYPES
/** /**
* Prepares a Slate document fragment to be copied to the clipboard. * Prepares a Slate document fragment to be copied to the clipboard.
@@ -33,7 +36,7 @@ function cloneFragment(event, value, fragment = value.fragment) {
// Make sure attach is a non-empty node, since empty nodes will not get copied // Make sure attach is a non-empty node, since empty nodes will not get copied
contents.childNodes.forEach(node => { contents.childNodes.forEach(node => {
if (node.innerText.trim() !== '') { if (node.innerText && node.innerText.trim() !== '') {
attach = node attach = node
} }
}) })
@@ -108,31 +111,30 @@ function cloneFragment(event, value, fragment = value.fragment) {
attach.setAttribute('data-slate-fragment', encoded) attach.setAttribute('data-slate-fragment', encoded)
// Add the phony content to the DOM, and select it, so it will be copied. // Add the phony content to a div element. This is needed to copy the
const editor = event.target.closest('[data-slate-editor]') // contents into the html clipboard register.
const div = window.document.createElement('div') const div = window.document.createElement('div')
div.appendChild(contents)
// For browsers supporting it, we set the clipboard registers manually,
// since the result is more predictable.
if (event.clipboardData && event.clipboardData.setData) {
event.preventDefault()
event.clipboardData.setData(TEXT, native.toString())
event.clipboardData.setData(FRAGMENT, encoded)
event.clipboardData.setData(HTML, div.innerHTML)
return
}
// COMPAT: For browser that don't support the Clipboard API's setData method,
// we must rely on the browser to natively copy what's selected.
// So we add the div (containing our content) to the DOM, and select it.
const editor = event.target.closest('[data-slate-editor]')
div.setAttribute('contenteditable', true) div.setAttribute('contenteditable', true)
div.style.position = 'absolute' div.style.position = 'absolute'
div.style.left = '-9999px' div.style.left = '-9999px'
// COMPAT: In Firefox, the viewport jumps to find the phony div, so it
// should be created at the current scroll offset with `style.top`.
// The box model attributes which can interact with 'top' are also reset.
div.style.border = '0px'
div.style.padding = '0px'
div.style.margin = '0px'
div.style.top = `${window.pageYOffset ||
window.document.documentElement.scrollTop}px`
div.appendChild(contents)
editor.appendChild(div) editor.appendChild(div)
native.selectAllChildren(div)
// COMPAT: In Firefox, trying to use the terser `native.selectAllChildren`
// throws an error, so we use the older `range` equivalent. (2016/06/21)
const r = window.document.createRange()
r.selectNodeContents(div)
removeAllRanges(native)
native.addRange(r)
// Revert to the previous selection right after copying. // Revert to the previous selection right after copying.
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {