IE TextRange选择方法无法正常工作

Dou*_*yle 7 javascript internet-explorer

对于将contentEditable设置为true的IE文档,我遇到了一个不寻常的问题.在位于紧邻块元素之前的文本节点末尾的范围上调用select()会使选择转移到右边的一个字符,并显示在不应该出现的位置.我已向Microsoft提交了针对IE8的错误.如果可以,请为此问题投票,以便修复.

https://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=390995

我写了一个测试用例来证明效果:

<html>
  <body>
    <iframe id="editable">
      <html>
        <body>
          <div id="test">
            Click to the right of this line -&gt;
            <p id="par">Block Element</p>
          </div>
        </body>
      </html>
    </iframe>
    <input id="mytrigger" type="button" value="Then Click here to Save and Restore" />
    <script type="text/javascript">
        window.onload = function() {
            var iframe = document.getElementById('editable');
            var doc = iframe.contentDocument || iframe.contentWindow.document;

            // An IFRAME without a source points to a blank document.  Here we'll
            // copy the content we stored in between the IFRAME tags into that
            // document.  It's a hack to allow us to use only one HTML file for this
            // test.
            doc.body.innerHTML = iframe.textContent || iframe.innerHTML;

            // Marke the IFRAME as an editable document
            if (doc.body.contentEditable) {
                doc.body.contentEditable = true;
            } else {
                var mydoc = doc;
                doc.designMode = 'On';
            }

            // A function to demonstrate the bug.
            var myhandler = function() {
                // Step 1 Get the current selection
                var selection = doc.selection || iframe.contentWindow.getSelection();
                var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0);

                // Step 2 Restore the selection
                if (range.select) {
                    range.select();
                } else {
                    selection.removeAllRanges();
                    selection.addRange(range);
                    doc.body.focus();
                }
            }

            // Set up the button to perform the test code.
            var button = document.getElementById('mytrigger');
            if (button.addEventListener) {
                button.addEventListener('click', myhandler, false);
            } else {
                button.attachEvent('onclick', myhandler);
            }
          }
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

问题暴露在myhandler函数中.这就是我正在做的事情,在保存和恢复选择之间没有第3步,但光标移动了.除非选择为空(即我有一个闪烁的光标,但没有文本),似乎不会发生这种情况,并且只有当光标位于紧接在块节点之前的文本节点的末尾时,它才会发生.

似乎范围仍然在正确的位置(如果我在它返回div的范围内调用parentElement),但是如果我从当前选择中获得新范围,则新范围在段落标记内,这就是它parentElement.

如何解决此问题并始终保存并恢复Internet Explorer中的选择?

小智 12

我已经找到了一些处理这样的IE范围的方法.

如果您只想保存光标所在的位置,然后将其恢复,则可以使用pasteHTML方法在光标的当前位置插入空跨度,然后使用moveToElementText方法将其放回到该位置再次:

// Save position of cursor
range.pasteHTML('<span id="caret"></span>')

...

// Create new cursor and put it in the old position
var caretSpan = iframe.contentWindow.document.getElementById("caret");
var selection = iframe.contentWindow.document.selection;
newRange = selection.createRange();
newRange.moveToElementText(caretSpan);
Run Code Online (Sandbox Code Playgroud)

或者,您可以计算当前光标位置前面的字符数并保存该数字:

var selection = iframe.contentWindow.document.selection;
var range = selection.createRange().duplicate();
range.moveStart('sentence', -1000000);
var cursorPosition = range.text.length;
Run Code Online (Sandbox Code Playgroud)

要恢复光标,请将其设置为开头,然后将其移动该字符数:

var newRange = selection.createRange();
newRange.move('sentence', -1000000);
newRange.move('character', cursorPosition);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.