有没有被Internet Explorer认可的替代selectionStart和selectionEnd的方法?

20

找出在真实浏览器中选择的内容就像这样简单:

var range = {
  start: textbox.selectionStart,
  end: textbox.selectionEnd
}

但是像往常一样,IE并不理解。什么是最好的跨浏览器实现方式?

4个回答

24
我会在另一个时间发布此函数,因为这个问题被链接到了另一个问题。
以下代码将在所有浏览器中运行,并处理所有换行符的问题,而不会严重影响性能。经过一些来回调整,我现在相信它是最好的这样的功能。
更新
此函数假定文本区域/输入具有焦点,因此您可能需要在调用它之前调用文本区域的focus()方法。
function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

var el = document.getElementById("your_input");
el.focus();
var sel = getInputSelection(el);
alert(sel.start + ", " + sel.end);

2
我们能够将其授权于某些非病毒式许可证,甚至捐赠给公共领域吗?(这是那些关心版权的人的声音 :)) - Tomasz Zieliński
1
@Tomasz:嗯,我把文本区域/输入选择的东西移到了一个单独的库中,因为它与文档内的选择完全不同:http://code.google.com/p/rangyinputs/。关于许可证,标准的Stack Overflow创意共享许可证有什么问题吗? - Tim Down
2
@Tomasz:好的,我理解自由软件许可证的细节很令人困惑和乏味,但我了解其一般原则。对于我要赠送的东西,我会愉快地以最方便用户的方式进行许可。 - Tim Down
我这里返回了0,0。我有什么遗漏吗? - Sandeepan Nath
这在IE8中对我来说不起作用。但是,如果我删除所有引用“normalizedValue”的行,它就可以正常工作。我还需要在处理IE8的部分顶部添加“el.focus()”。其他浏览器不需要焦点。 - PKKid
显示剩余6条评论

7

IE的范围实现是一种可怕的恶梦。它真的希望你使用令人讨厌的execCommand接口,而不是任何涉及文本索引的东西。

我知道两种获取索引的方法,它们都有问题。第一种方法使用range.text,就像你的示例代码中那样。不幸的是,range.text有一个习惯,即剥离前导和尾随换行符,这意味着如果插入符/选择位于除第一行之外的某一行的开头,则beforeLength将偏移(换行符数*2)个字符,从而得到错误的选定文本。

第二种方法是使用range.moveStart/End(在复制的范围上),如回答Internet Explorer TextRange中的字符偏移中所述(但由于您正在使用已知的textarea父级,因此可以忽略有关节点查找的内容)。这没有同样的问题,但它会报告所有索引,就好像换行符是简单的LF字符一样,即使textarea.value和range.text将它们作为CRLF序列返回!因此,您不能直接使用它们来索引textarea,但您可以通过大量的换行符计数来修复它们,或者在使用它之前将值中的所有CR替换掉。


6

我的当前解决方案很啰嗦,基于这个帖子,但我乐意接受更好的解决方案。

function getSelection(inputBox) {
    if ("selectionStart" in inputBox) {
        return {
            start: inputBox.selectionStart,
            end: inputBox.selectionEnd
        }
    }

    //and now, the blinkered IE way
    var bookmark = document.selection.createRange().getBookmark()
    var selection = inputBox.createTextRange()
    selection.moveToBookmark(bookmark)

    var before = inputBox.createTextRange()
    before.collapse(true)
    before.setEndPoint("EndToStart", selection)

    var beforeLength = before.text.length
    var selLength = selection.text.length

    return {
        start: beforeLength,
        end: beforeLength + selLength
    }
}

这个问题和换行有关。查看@bobince的答案了解一些背景信息,我的答案提供了解决方案。 - Tim Down

0

来自BootstrapFormHelpers

  function getCursorPosition($element) {
    var position = 0,
        selection;

    if (document.selection) {
      // IE Support
      $element.focus();
      selection = document.selection.createRange();
      selection.moveStart ('character', -$element.value.length);
      position = selection.text.length;
    } else if ($element.selectionStart || $element.selectionStart === 0) {
      position = $element.selectionStart;
    }

    return position;
  }

  function setCursorPosition($element, position) {
    var selection;

    if (document.selection) {
      // IE Support
      $element.focus ();
      selection = document.selection.createRange();
      selection.moveStart ('character', -$element.value.length);
      selection.moveStart ('character', position);
      selection.moveEnd ('character', 0);
      selection.select ();
    } else if ($element.selectionStart || $element.selectionStart === 0) {
      $element.selectionStart = position;
      $element.selectionEnd = position;
      $element.focus ();
    }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接