diff --git a/src/components/content.js b/src/components/content.js index 091580be6..bcd665313 100644 --- a/src/components/content.js +++ b/src/components/content.js @@ -3,6 +3,7 @@ import Base64 from '../serializers/base-64' import Debug from 'debug' import Node from './node' import getPoint from '../utils/get-point' +import extendSelection from '../utils/extend-selection' import findClosestNode from '../utils/find-closest-node' import React from 'react' import Selection from '../models/selection' @@ -207,7 +208,7 @@ class Content extends React.Component { const range = window.document.createRange() range.setStart(anchorEl, anchorOff) native.addRange(range) - native.extend(focusEl, focusOff) + extendSelection(native, focusEl, focusOff) // Then unset the `isSelecting` flag after a delay. setTimeout(() => { diff --git a/src/utils/extend-selection.js b/src/utils/extend-selection.js new file mode 100644 index 000000000..1ec8f2596 --- /dev/null +++ b/src/utils/extend-selection.js @@ -0,0 +1,45 @@ + +/** + * Extends the given selection to a given node and offset + * + * @param {Selection} selection Selection instance + * @param {Element} el Node to extend to + * @param {Number} offset Text offset to extend to + * @returns {Selection} Mutated Selection instance + */ + +function extendSelection(selection, el, offset) { + // Use native method when possible + if (typeof selection.extend === 'function') return selection.extend(el, offset) + + // See https://gist.github.com/tyler-johnson/0a3e8818de3f115b2a2dc47468ac0099 + const range = document.createRange() + const anchor = document.createRange() + anchor.setStart(selection.anchorNode, selection.anchorOffset) + + const focus = document.createRange() + focus.setStart(el, offset) + + const v = focus.compareBoundaryPoints(Range.START_TO_START, anchor) + if (v >= 0) { // Focus is after anchor + range.setStart(selection.anchorNode, selection.anchorOffset) + range.setEnd(el, offset) + } else { // Anchor is after focus + range.setStart(el, offset) + range.setEnd(selection.anchorNode, selection.anchorOffset) + } + + selection.removeAllRanges() + selection.addRange(range) + + return selection +} + + +/** + * Export. + * + * @type {Function} + */ + +export default extendSelection