ShadowRoot's getSelection().getRangeAt(0) returns incorrect Range object in Google Chrome 35

dart, html, javascript, polymer, shadow-dom

Solution

Seems like it is a bug reported by me here and confirmed by the chromium team at the end of the issue thread.

Problem

We're working on an application for our customer that uses dart lang with polymer components. One of our custom components namely datagrid uses `<div contenteditable></div>` for entering values to the datagrid cells. I also want to provide custom formatting capabilities so I had to override keypress event. The problem araises when I want to create new HTML nodes at the caret position within the content-editable div element in Chrome 35 (possibly all webkit browsers that support Shadow DOM natively, not through polyfills). When I use `window.getSelection().getRangeAt(0)` to get current caret position, new nodes are being added to the beginning of the body element instead of the div. In Firefox and IE 11 it works great though (using polyfill). When I tried `this.shadowRoot.getSelection().getRangeAt(0)` as suggested here it didn't work as well because it returns incorrect Range object (a bug or a feature?). However when I logged the Selection object, it seems like all offsets are correct so it means that it can be worked around somehow but the guy that asked similar question on SO hasn't posted how he did it. So I don't know, how to create a Range object from given offset when content-editable div contains multiple HTML nodes as browsers like to create multiple nodes when you put a line break into the middle of the word and delete it immediately (as a side question, is it normal anyways? doesn't it cause memory leaks?). It then looks like this in a Chrome console (#cell-input here has 4 nodes although it just contains continuous string "Marek"): ``` <div contenteditable="true" id="cell-input"> "M" "ar" "ek" <br> </div> ``` I tried to use something like (it's just a pseudocode): ``` offset = shadowRoot.getSelection().extentOffset; element = document.querySelector('cell-input'); range = document.createRange(); range.setStart(element.children.first, offset ); range.setEnd(element.children.first, offset); range.collapse(false); ``` ... but it didn't work properly. Any ideas?

Original source

Related problems