@@ -12,7 +12,7 @@ import highlightSupport from './highlight-support'
1212import Highlighting from './highlighting'
1313import createDefaultEvents from './create-default-events'
1414import browser from 'bowser'
15- import { getTotalCharCount , textNodesUnder , getTextNodeAndRelativeOffset } from './util/element'
15+ import { textNodesUnder , getTextNodeAndRelativeOffset } from './util/element'
1616import { binaryCursorSearch } from './util/binary_search'
1717
1818/**
@@ -195,16 +195,15 @@ export default class Editable {
195195 */
196196
197197 createCursor ( element , position = 'beginning' ) {
198- const $host = $ ( element ) . closest ( this . editableSelector )
199-
200- if ( ! $host . length ) return undefined
198+ const host = Cursor . findHost ( element , this . editableSelector )
199+ if ( ! host ) return undefined
201200
202201 const range = rangy . createRange ( )
203202
204203 if ( position === 'beginning' || position === 'end' ) {
205204 range . selectNodeContents ( element )
206205 range . collapse ( position === 'beginning' )
207- } else if ( element !== $ host[ 0 ] ) {
206+ } else if ( element !== host ) {
208207 if ( position === 'before' ) {
209208 range . setStartBefore ( element )
210209 range . setEndBefore ( element )
@@ -216,26 +215,19 @@ export default class Editable {
216215 error ( 'EditableJS: cannot create cursor outside of an editable block.' )
217216 }
218217
219- return new Cursor ( $host [ 0 ] , range )
220- }
221-
222- createRangyRange ( ) {
223- return rangy . createRange ( )
224- }
225-
226- createCursorWithRange ( { element, range} ) {
227- const $host = $ ( element ) . closest ( this . editableSelector )
228- return new Cursor ( $host [ 0 ] , range )
218+ return new Cursor ( host , range )
229219 }
230220
231221 createCursorAtCharacterOffset ( { element, offset} ) {
232222 const textNodes = textNodesUnder ( element )
233223 const { node, relativeOffset} = getTextNodeAndRelativeOffset ( { textNodes, absOffset : offset } )
234- const newRange = this . createRangyRange ( )
224+ const newRange = rangy . createRange ( )
235225 newRange . setStart ( node , relativeOffset )
236- newRange . setEnd ( node , relativeOffset )
237- newRange . collapse ( )
238- const nextCursor = this . createCursorWithRange ( { element, range : newRange } )
226+ newRange . collapse ( true )
227+
228+ const host = Cursor . findHost ( element , this . editableSelector )
229+ const nextCursor = new Cursor ( host , newRange )
230+
239231 nextCursor . setVisibleSelection ( )
240232 return nextCursor
241233 }
@@ -470,83 +462,42 @@ export default class Editable {
470462 return this
471463 }
472464
473- /*
474- Takes coordinates and uses its left value to find out how to offset a character in a string to
475- closely match the coordinates.left value.
476- Takes conditions for the result being on the first line, used when navigating to a paragraph from
477- the above paragraph and being on the last line, used when navigating to a paragraph from the below
478- paragraph.
479-
480- Internally this sets up the methods used for a binary cursor search and calls this.
481-
482- @param {DomNode } element The DOM Node (usually editable elem) to which the cursor jumps
483- @param {Object } coordinates The bounding rect of the preceeding cursor to be matched
484- @param {Boolean } requiredOnFirstLine set to true if you want to require the cursor to be on the first line of the paragraph
485- @param {Boolean } requiredOnLastLine set to true if you want to require the cursor to be on the last line of the paragraph
486-
487- @return {Object } object with boolean `wasFound` indicating if the binary search found an offset and `offset` to indicate the actual character offset
488- */
489- findClosestCursorOffset (
490- { element, origCoordinates, requiredOnFirstLine = false , requiredOnLastLine = false } ) {
491- // early terminate on empty editables
492- const totalCharCount = getTotalCharCount ( element )
493- if ( totalCharCount === 0 ) return { wasFound : false }
494- // move left if the coordinates are to the left
495- const leftCondition = ( { data, coordinates} ) => {
496- if ( coordinates . left >= data . origCoordinates . left ) return true
497- return false
498- }
499- // move up if cursor is required to be on first line but is currently not
500- const upCondition = ( { data, cursor} ) => {
501- if ( data . requiredOnFirstLine && ! cursor . isAtFirstLine ( ) ) return true
502- return false
503- }
504- // move down if cursor is required to be on last line but is currently not
505- const downCondition = ( { data, cursor} ) => {
506- if ( data . requiredOnLastLine && ! cursor . isAtLastLine ( ) ) return true
507- return false
508- }
509- // move the binary search index in between the current position and the left limit
510- const moveLeft = ( data ) => {
511- data . rightLimit = data . currentOffset
512- data . currentOffset = Math . floor ( ( data . currentOffset - data . leftLimit ) / 2 )
513- }
514- // move the binary search index in between the current position and the right limit
515- const moveRight = ( data ) => {
516- data . leftLimit = data . currentOffset
517- data . currentOffset = data . currentOffset + Math . floor ( ( data . rightLimit - data . currentOffset ) / 2 )
518- }
519- // consider a small bluriness since character never exactly match coordinates
520- const foundChecker = ( { distance, bluriness} ) => {
521- return distance <= bluriness
522- }
523- // consider converged if 2 consecutive history entries are equal
524- const convergenceChecker = ( history ) => {
525- const lastTwo = history . slice ( - 2 )
526- if ( lastTwo . length === 2 && lastTwo [ 0 ] === lastTwo [ 1 ] ) return true
527- return false
528- }
465+ /**
466+ * Takes coordinates and uses its left value to find out how to offset a character in a string to
467+ * closely match the coordinates.left value.
468+ * Takes conditions for the result being on the first line, used when navigating to a paragraph from
469+ * the above paragraph and being on the last line, used when navigating to a paragraph from the below
470+ * paragraph.
471+ *
472+ * Internally this sets up the methods used for a binary cursor search and calls this.
473+ *
474+ * @param {DomNode } element
475+ * - the editable hostDOM Node to which the cursor jumps
476+ * @param {object } coordinates
477+ * - The bounding rect of the preceeding cursor to be matched
478+ * @param {boolean } requiredOnFirstLine
479+ * - set to true if you want to require the cursor to be on the first line of the paragraph
480+ * @param {boolean } requiredOnLastLine
481+ * - set to true if you want to require the cursor to be on the last line of the paragraph
482+ *
483+ * @return {Object }
484+ * - object with boolean `wasFound` indicating if the binary search found an offset and `offset` to indicate the actual character offset
485+ */
486+ findClosestCursorOffset ( {
487+ element,
488+ origCoordinates,
489+ requiredOnFirstLine = false ,
490+ requiredOnLastLine = false
491+ } ) {
492+ const positionX = this . dispatcher . switchContext
493+ ? this . dispatcher . switchContext . positionX
494+ : origCoordinates . left
529495
530- const data = {
531- element,
532- currentOffset : Math . floor ( totalCharCount / 2 ) ,
533- rightLimit : totalCharCount ,
534- leftLimit : 0 ,
496+ return binaryCursorSearch ( {
497+ host : element ,
535498 requiredOnFirstLine,
536499 requiredOnLastLine,
537- origCoordinates
538- }
539-
540- return binaryCursorSearch ( {
541- moveLeft,
542- moveRight,
543- leftCondition,
544- upCondition,
545- downCondition,
546- convergenceChecker,
547- foundChecker,
548- createCursorAtCharacterOffset : this . createCursorAtCharacterOffset . bind ( this ) ,
549- data
500+ positionX
550501 } )
551502 }
552503}
0 commit comments