import { cloneDeep } from "lodash" ; import Editor from "../editor" ; import { getUtf8TextLengthFromJsOffset } from "../util/text-util" ; import { getElememtSize , getContainer , Cursor , getCursorElement , getOffset } from "./util" ; export interface selectionType { isCollapsed : boolean ; range : [ Cursor , Cursor ] ; } let selectionStore = { isCollapsed : true , range : [ { id : "" , offset : 0 , } , { id : "" , offset : 0 , } , ] , } ; const getSelection = ( editor ) => { let contentWindow = editor . mountedWindow ; let section = contentWindow . getSelection ( ) ; if ( ! section || ! section . anchorNode || ! section . focusNode || section ?. type === "None" ) { return cloneDeep < selectionType > ( selectionStore ) ; } let anchorNode = section . anchorNode as HTMLElement ; let rootDom = contentWindow . document . getElementById ( "zebra-editor-contain" ) ; if ( ! rootDom ?. contains ( anchorNode ) ) { return cloneDeep < selectionType > ( selectionStore ) ; } if ( rootDom === anchorNode || ( anchorNode . dataset && anchorNode . dataset . type === "ARTICLE" ) ) { let startBlock = rootDom ; let endBlock = rootDom ; while ( startBlock . dataset && startBlock . dataset . structure !== "CONTENT" ) { startBlock = startBlock . children [ 0 ] as HTMLElement ; } while ( endBlock . dataset && endBlock . dataset . structure !== "CONTENT" ) { endBlock = endBlock . children [ endBlock . children . length - 1 ] as HTMLElement ; } selectionStore = { isCollapsed : section . isCollapsed , range : [ { id : startBlock . id , offset : 0 , } , { id : endBlock . id , offset : - 1 , } , ] , } ; return cloneDeep < selectionType > ( selectionStore ) ; } if ( anchorNode . dataset && anchorNode . dataset . structure === "CONTENT" ) { let startParent = getCursorElement ( anchorNode ) ; let offset = 0 ; for ( let i = 0 ; i < section . anchorOffset ; i ++ ) { offset += getElememtSize ( anchorNode . children [ i ] as HTMLElement ) ; } selectionStore = { isCollapsed : true , range : [ { id : startParent . id , offset : offset , } , { id : startParent . id , offset : offset , } , ] , } ; return cloneDeep < selectionType > ( selectionStore ) ; } let posiType = section . anchorNode . compareDocumentPosition ( section . focusNode ) ; let anchorOffset = section . anchorOffset ; let focusOffset = section . focusOffset ; if ( section . anchorNode . nodeType === 3 ) { anchorOffset = getUtf8TextLengthFromJsOffset ( section . anchorNode . textContent , anchorOffset ) ; } if ( section . focusNode . nodeType === 3 ) { focusOffset = getUtf8TextLengthFromJsOffset ( section . focusNode . textContent , focusOffset ) ; } let startOffset ; let startNode ; let endOffset ; let endNode ; if ( posiType === 0 ) { if ( anchorOffset > focusOffset ) { startOffset = focusOffset ; startNode = section ?. focusNode ; endOffset = anchorOffset ; endNode = section ?. anchorNode ; } else { startOffset = anchorOffset ; startNode = section ?. anchorNode ; endOffset = focusOffset ; endNode = section ?. focusNode ; } } else if ( posiType === 2 ) { startOffset = focusOffset ; startNode = section ?. focusNode ; endOffset = anchorOffset ; endNode = section ?. anchorNode ; } else { startOffset = anchorOffset ; startNode = section ?. anchorNode ; endOffset = focusOffset ; endNode = section ?. focusNode ; } let startParagtaph = getCursorElement ( startNode as HTMLElement ) ; let startContainer = getContainer ( startNode as HTMLElement ) ; let endParagraph = getCursorElement ( endNode as HTMLElement ) ; let endContainer = getContainer ( endNode as HTMLElement ) ; startOffset = getOffset ( startParagtaph , startContainer , startOffset ) ; endOffset = getOffset ( endParagraph , endContainer , endOffset ) ; selectionStore = { isCollapsed : section ?. isCollapsed === undefined ? true : section . isCollapsed , range : [ { id : startParagtaph . id , offset : startOffset , } , { id : endParagraph . id , offset : endOffset , } , ] , } ; return cloneDeep < selectionType > ( selectionStore ) ; } ; export default getSelection ;