Search code examples
ckeditorrangeselection

Triple selection in Chrome result in multiple line selection


I'm implementing a WYSIWYG on top of CKEditor4 ( basically I'm just rewriting the toolbar ). The problem is that dragging the mouse to select and triple-clicking a line to select it, produces different ranges.

With this html:

<h2>^Leo ac scegliere e iniziare^</h2> <<< Line I want to select
<p>nunc ultrices eros, sed gravida</p>

These are the ranges produced in different scenarios:

right-to-left and left-to-right

startContainer and endContainer are the same, it reflects the actual situation from the user point of view.

collapsed: false
document:CKEDITOR.dom.document {$: document}
endContainer: CKEDITOR.dom.element {$: h2, getName: ƒ}
endOffset: 1 
startContainer: CKEDITOR.dom.element {$: h2, getName: ƒ}
startOffset: 0

triple-selection

startContainer and endContainer are not the same, it doesn't reflect the actual situation from the user point of view.

collapsed: false
document:CKEDITOR.dom.document {$: document}
endContainer: CKEDITOR.dom.element {$: p, getName: ƒ}
endOffset: 0 
startContainer: CKEDITOR.dom.element {$: h2, getName: ƒ}
startOffset: 0

This difference is causing me problems in style applying. This is happening in Chrome but not in Firefox.

Any idea of why is this happening? Any solution? I've been thinking about a solution that checks the endContainer and endOffset but I'm afraid that such solution can break range and selection providing unexpected behaviors


Solution

  • As result of a mouseup event I came up with this:

    fuction handleMouseup(event) {
      if (event.detail === 3) {
        const selection = this.editor.getSelection()
        let range = selection.getRanges()[0]
        let actualStartContainer = range.startContainer
    
        // Finds the highest parent untill the startContainer
        while (!actualStartContainer.getParent().equals(this.editor.element))
            actualStartContainer = actualStartContainer.getParent()
    
        // Select the ranges and update the selection with just the startContainer
        range.selectNodeContents(actualStartContainer)
        selection.selectRanges([range])
      }
    }