是否有 Internet Explorer 认可的 SelectionStart 和 SelectionEnd 替代品?

发布于 2024-07-07 11:59:48 字数 173 浏览 13 评论 0原文

找出真实浏览器中选择的内容非常简单:

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

但是 IE 像往常一样不理解。 执行此操作的最佳跨浏览器方法是什么?

Finding out what's selected in real browsers is as simple as:

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

But IE, as usual, doesn't understand. What's the best cross-browser way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ぃ弥猫深巷。 2024-07-14 11:59:48

我将再次发布此功能,因为这个问题已与另一个问题相关联。

以下内容将在所有浏览器中完成这项工作,并处理所有新行问题,而不会严重影响性能。 经过一些调整和现在我非常确信这是最好的此类功能。

UPDATE

此函数确实假设文本区域/输入具有焦点,因此您可能需要在调用它之前调用文本区域的 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);

I'll post this function for another time, seeing as this question got linked to from another one.

The following will do the job in all browsers and deals with all new line problems without seriously compromising performance. I've arrived at this after some toing and froing and now I'm pretty convinced it's the best such function around.

UPDATE

This function does assume the textarea/input has focus, so you may need to call the textarea's focus() method before calling it.

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);
剑心龙吟 2024-07-14 11:59:48

IE 的 Range 实现是一个令人毛骨悚然的恐怖。 它确实希望您使用可恶的 execCommand 接口,而不是任何涉及文本索引的东西。

我知道有两种获取索引的方法,但它们都有问题。 第一个使用 range.text,如示例代码中所示。 不幸的是 range.text 有去除前导和尾随换行符的习惯,这意味着如果插入符号/选择位于第一行以外的行的开头,则 beforeLength 将关闭(换行数*2)个字符,并且您会得到错误的选定文本。

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

IE's Range implementation is a slithy horror. It really wants you to use the execrable execCommand interface instead of anything involving indexing into the text.

There are two approaches I know of for getting the indices and they both have problems. The first uses range.text as in your example code. Unfortunately range.text has a habit of stripping off leading and trailing newlines, which means if the caret/selection is at the start of a line other than the first one, beforeLength will be off by (number of newlines*2) characters and you'll get the wrong selected text.

The second approach is to use range.moveStart/End (on a duplicated range), as outlined in the answer to this question: Character offset in an Internet Explorer TextRange (however as you are using a known textarea parent you can ignore the stuff about node-finding). This doesn't have the same problem, but it does report all indices as if newlines were simple LF characters, even though textarea.value and range.text will return them as CRLF sequences! So you can't use them directly to index into the textarea, but you can either fix them up with a bunch of newline counting or just string-replace away all the CRs from the value before you use it.

南风起 2024-07-14 11:59:48

我当前的解决方案很详细,并且基于此线程,但我接受更好的解决方案。

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
    }
}

My current solution is verbose and based on this thread, but I'm open to better solutions.

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
    }
}
神魇的王 2024-07-14 11:59:48

来自 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 ();
    }
  }

From 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 ();
    }
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文