mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-22 23:12:52 +02:00
feat: Add findClosestNode utility (#728)
* feat: Add findClosestNode utlity * A light shim utility that wraps the functionality of the native `closest` method * IE11 and Edge don't support the `closest` method on nodes * For those browsers that don't support it, we shim it with a shim taken from MDN * Linting fixes * Remove extra semi-colons as per lint guidelines
This commit is contained in:
committed by
Ian Storm Taylor
parent
f39c4327fe
commit
c36537c6e8
@@ -3,6 +3,7 @@ import Base64 from '../serializers/base-64'
|
|||||||
import Debug from 'debug'
|
import Debug from 'debug'
|
||||||
import Node from './node'
|
import Node from './node'
|
||||||
import getPoint from '../utils/get-point'
|
import getPoint from '../utils/get-point'
|
||||||
|
import findClosestNode from '../utils/find-closest-node'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Selection from '../models/selection'
|
import Selection from '../models/selection'
|
||||||
import getTransferData from '../utils/get-transfer-data'
|
import getTransferData from '../utils/get-transfer-data'
|
||||||
@@ -243,7 +244,7 @@ class Content extends React.Component {
|
|||||||
const { target } = event
|
const { target } = event
|
||||||
return (
|
return (
|
||||||
(target.isContentEditable) &&
|
(target.isContentEditable) &&
|
||||||
(target == element || target.closest('[data-slate-editor]') == element)
|
(target == element || findClosestNode(target, '[data-slate-editor]') == element)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
src/utils/find-closest-node.js
Normal file
32
src/utils/find-closest-node.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Find the closest ancestor of a DOM `element` that matches a given selector.
|
||||||
|
*
|
||||||
|
* @param {Element} node
|
||||||
|
* @param {String} selector
|
||||||
|
* @return {Element}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function findClosestNode(node, selector) {
|
||||||
|
if (typeof node.closest === 'function') return node.closest(selector)
|
||||||
|
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
|
||||||
|
const matches = (node.document || node.ownerDocument).querySelectorAll(selector)
|
||||||
|
let i
|
||||||
|
let parentNode = node
|
||||||
|
do {
|
||||||
|
i = matches.length
|
||||||
|
while (--i >= 0 && matches.item(i) !== parentNode);
|
||||||
|
}
|
||||||
|
while ((i < 0) && (parentNode = parentNode.parentElement))
|
||||||
|
|
||||||
|
return parentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export.
|
||||||
|
*
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default findClosestNode
|
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import normalizeNodeAndOffset from './normalize-node-and-offset'
|
import normalizeNodeAndOffset from './normalize-node-and-offset'
|
||||||
|
import findClosestNode from './find-closest-node'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offset key parser regex.
|
* Offset key parser regex.
|
||||||
@@ -68,12 +69,12 @@ function findKey(rawNode, rawOffset) {
|
|||||||
const { parentNode } = node
|
const { parentNode } = node
|
||||||
|
|
||||||
// Find the closest parent with an offset key attribute.
|
// Find the closest parent with an offset key attribute.
|
||||||
let closest = parentNode.closest(SELECTOR)
|
let closest = findClosestNode(parentNode, SELECTOR)
|
||||||
|
|
||||||
// For void nodes, the element with the offset key will be a cousin, not an
|
// For void nodes, the element with the offset key will be a cousin, not an
|
||||||
// ancestor, so find it by going down from the nearest void parent.
|
// ancestor, so find it by going down from the nearest void parent.
|
||||||
if (!closest) {
|
if (!closest) {
|
||||||
const closestVoid = parentNode.closest(VOID_SELECTOR)
|
const closestVoid = findClosestNode(parentNode, VOID_SELECTOR)
|
||||||
if (!closestVoid) return null
|
if (!closestVoid) return null
|
||||||
closest = closestVoid.querySelector(SELECTOR)
|
closest = closestVoid.querySelector(SELECTOR)
|
||||||
offset = closest.textContent.length
|
offset = closest.textContent.length
|
||||||
|
Reference in New Issue
Block a user