mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-02-21 23:53:50 +01:00
Core component will deduce the context from the dispatched event.target element
This commit is contained in:
parent
5fa616a01d
commit
186f1a7c6d
@ -9,6 +9,7 @@ import TYPES from '../utils/types'
|
||||
import includes from 'lodash/includes'
|
||||
import keycode from 'keycode'
|
||||
import { IS_FIREFOX, IS_MAC } from '../utils/environment'
|
||||
import findElementWindow from '../utils/find-element-window'
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
@ -380,11 +381,13 @@ class Content extends React.Component {
|
||||
// Resolve the point where the drop occured.
|
||||
let range
|
||||
|
||||
const contextWindow = findElementWindow(e.nativeEvent.target)
|
||||
|
||||
// COMPAT: In Firefox, `caretRangeFromPoint` doesn't exist. (2016/07/25)
|
||||
if (window.document.caretRangeFromPoint) {
|
||||
range = window.document.caretRangeFromPoint(x, y)
|
||||
if (contextWindow.document.caretRangeFromPoint) {
|
||||
range = contextWindow.document.caretRangeFromPoint(x, y)
|
||||
} else {
|
||||
range = window.document.createRange()
|
||||
range = contextWindow.document.createRange()
|
||||
range.setStart(e.nativeEvent.rangeParent, e.nativeEvent.rangeOffset)
|
||||
}
|
||||
|
||||
@ -459,9 +462,11 @@ class Content extends React.Component {
|
||||
if (isNonEditable(e)) return
|
||||
debug('onInput')
|
||||
|
||||
const contextWindow = findElementWindow(e.nativeEvent.target)
|
||||
|
||||
let { state, renderDecorations } = this.props
|
||||
const { selection } = state
|
||||
const native = window.getSelection()
|
||||
const native = contextWindow.getSelection()
|
||||
const { anchorNode, anchorOffset, focusOffset } = native
|
||||
const point = this.getPoint(anchorNode, anchorOffset)
|
||||
const { key, index, start, end } = point
|
||||
@ -624,9 +629,11 @@ class Content extends React.Component {
|
||||
if (this.tmp.isComposing) return
|
||||
if (isNonEditable(e)) return
|
||||
|
||||
const contextWindow = findElementWindow(e.nativeEvent.target)
|
||||
|
||||
const { state, renderDecorations } = this.props
|
||||
let { document, selection } = state
|
||||
const native = window.getSelection()
|
||||
const native = contextWindow.getSelection()
|
||||
const data = {}
|
||||
|
||||
// If there are no ranges, the editor was blurred natively.
|
||||
|
@ -3,7 +3,7 @@ import Debug from 'debug'
|
||||
import OffsetKey from '../utils/offset-key'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import findElementWindow from '../utils/find-element-window'
|
||||
/**
|
||||
* Debugger.
|
||||
*
|
||||
@ -135,14 +135,16 @@ class Leaf extends React.Component {
|
||||
focusOffset = 0
|
||||
}
|
||||
|
||||
const contextWindow = findElementWindow(ReactDOM.findDOMNode(this));
|
||||
|
||||
// We have a selection to render, so prepare a few things...
|
||||
const native = window.getSelection()
|
||||
const native = contextWindow.getSelection()
|
||||
const el = findDeepestNode(ReactDOM.findDOMNode(this))
|
||||
|
||||
// If both the start and end are here, set the selection all at once.
|
||||
if (hasAnchor && hasFocus) {
|
||||
native.removeAllRanges()
|
||||
const range = window.document.createRange()
|
||||
const range = contextWindow.document.createRange()
|
||||
range.setStart(el, anchorOffset - start)
|
||||
native.addRange(range)
|
||||
native.extend(el, focusOffset - start)
|
||||
@ -155,7 +157,7 @@ class Leaf extends React.Component {
|
||||
if (selection.isForward) {
|
||||
if (hasAnchor) {
|
||||
native.removeAllRanges()
|
||||
const range = window.document.createRange()
|
||||
const range = contextWindow.document.createRange()
|
||||
range.setStart(el, anchorOffset - start)
|
||||
native.addRange(range)
|
||||
} else if (hasFocus) {
|
||||
@ -170,14 +172,14 @@ class Leaf extends React.Component {
|
||||
else {
|
||||
if (hasFocus) {
|
||||
native.removeAllRanges()
|
||||
const range = window.document.createRange()
|
||||
const range = contextWindow.document.createRange()
|
||||
range.setStart(el, focusOffset - start)
|
||||
native.addRange(range)
|
||||
} else if (hasAnchor) {
|
||||
const endNode = native.focusNode
|
||||
const endOffset = native.focusOffset
|
||||
native.removeAllRanges()
|
||||
const range = window.document.createRange()
|
||||
const range = contextWindow.document.createRange()
|
||||
range.setStart(el, anchorOffset - start)
|
||||
native.addRange(range)
|
||||
native.extend(endNode, endOffset)
|
||||
|
@ -5,6 +5,7 @@ import Debug from 'debug'
|
||||
import Placeholder from '../components/placeholder'
|
||||
import React from 'react'
|
||||
import String from '../utils/string'
|
||||
import findElementWindow from '../utils/find-element-window'
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
@ -28,7 +29,7 @@ function Plugin(options = {}) {
|
||||
const {
|
||||
placeholder,
|
||||
placeholderClassName,
|
||||
placeholderStyle
|
||||
placeholderStyle,
|
||||
} = options
|
||||
|
||||
/**
|
||||
@ -204,7 +205,9 @@ function Plugin(options = {}) {
|
||||
*/
|
||||
|
||||
function onCutOrCopy(e, data, state) {
|
||||
const native = window.getSelection()
|
||||
const contextWindow = findElementWindow(e.nativeEvent.target)
|
||||
|
||||
const native = contextWindow.getSelection()
|
||||
if (!native.rangeCount) return
|
||||
|
||||
const { fragment } = data
|
||||
@ -214,10 +217,10 @@ function Plugin(options = {}) {
|
||||
// fragment attached as an attribute, so it will show up in the copied HTML.
|
||||
const range = native.getRangeAt(0)
|
||||
const contents = range.cloneContents()
|
||||
const wrapper = window.document.createElement('span')
|
||||
const wrapper = contextWindow.document.createElement('span')
|
||||
const text = contents.childNodes[0]
|
||||
const char = text.textContent.slice(0, 1)
|
||||
const first = window.document.createTextNode(char)
|
||||
const first = contextWindow.document.createTextNode(char)
|
||||
const rest = text.textContent.slice(1)
|
||||
text.textContent = rest
|
||||
wrapper.appendChild(first)
|
||||
@ -225,8 +228,8 @@ function Plugin(options = {}) {
|
||||
contents.insertBefore(wrapper, text)
|
||||
|
||||
// Add the phony content to the DOM, and select it, so it will be copied.
|
||||
const body = window.document.querySelector('body')
|
||||
const div = window.document.createElement('div')
|
||||
const body = contextWindow.document.querySelector('body')
|
||||
const div = contextWindow.document.createElement('div')
|
||||
div.setAttribute('contenteditable', true)
|
||||
div.style.position = 'absolute'
|
||||
div.style.left = '-9999px'
|
||||
@ -235,7 +238,7 @@ function Plugin(options = {}) {
|
||||
|
||||
// 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()
|
||||
const r = contextWindow.document.createRange()
|
||||
r.selectNodeContents(div)
|
||||
native.removeAllRanges()
|
||||
native.addRange(r)
|
||||
|
12
lib/utils/find-element-window.js
Normal file
12
lib/utils/find-element-window.js
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Find the DOM context for the `node`, fallback to top level global window object.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @return {Element} el
|
||||
*/
|
||||
function findElementWindow (domNode) {
|
||||
const doc = domNode.ownerDocument || domNode
|
||||
return doc.defaultView || doc.parentWindow
|
||||
}
|
||||
|
||||
export default findElementWindow
|
Loading…
x
Reference in New Issue
Block a user