【问题标题】:Ace selects all text in editor on focus in FirefoxAce 在 Firefox 中选择编辑器中的所有文本
【发布时间】:2015-01-21 04:52:16
【问题描述】:

我在 Bootstrap 3 模式中嵌入了一个 Ace 编辑器。在显示模态之前,我在编辑器中设置了这样的值:

var editor = ace.edit(aceEditorId);
editor.session.setValue(val, -1); // set value at document start
editor.session.selection.clearSelection();

我还有一个用于调整编辑器大小的模式的“显示”事件处理程序:

$(editSnippetSelector).on("shown.bs.modal", function () {
        var editorId = getSnippetEditorId();
        var snippetEditor = ace.edit(editorId);
        snippetEditor.resize();

当我专注于 Firefox 中的编辑器时,所有的编辑器文本都会被选中。我无法移动光标或通过单击删除选择。我只能通过按退格键或其他键(例如字母或回车键)擦除文本。

这在 Chrome 或 IE 中不会发生。

作为实验,我也添加了这段代码,但无济于事:

codeEditor.on("focus", function () {
    codeEditor.getSession().setValue(codeEditor.getSession().getValue());
    codeEditor.clearSelection();
});

我还应该去哪里看?有没有其他人看到过类似的行为?

更新:

我注意到ace.js 中有一个onSelect 函数在无限循环中被调用。上线2061:https://github.com/ajaxorg/ace-builds/blob/master/src-noconflict/ace.js#L2061

这里是函数的代码:

var onSelect = function(e) {
    if (copied) {
        copied = false;
    } else if (isAllSelected(text)) {
        host.selectAll();
        resetSelection();
    } else if (inputHandler) {
        resetSelection(host.selection.isEmpty());
    }
};

浏览 Firefox 调试器中的代码显示,对 isAllSelected(text) 的调用返回 true,因此再次引发了选择事件。

【问题讨论】:

    标签: firefox ace-editor


    【解决方案1】:

    ace.js 有一个 onSelect 处理程序,它在 Firefox 中被无限循环调用。

    这是该函数的原始代码:

    var onSelect = function(e) {
        if (copied) {
            copied = false;
        } else if (isAllSelected(text)) {
            host.selectAll();
            resetSelection();
        } else if (inputHandler) {
            resetSelection(host.selection.isEmpty());
        }
    };
    

    text 是一个 textarea DOM 元素。 isAllSelected(text) 检查是否使用此代码选择了所有文本:

        return text.selectionStart === 0 && text.selectionEnd === text.value.length;
    

    正如您所见,即使对于空文本区域,这也会返回 true,然后会导致调用 host.selectAll(),它会以某种方式向下传播并再次触发 select 事件。

    我添加了对空文本区域的检查,它解决了问题。代码现在是这样的:

    var onSelect = function(e) {
        if (copied) {
            copied = false;
        } else if (text.value && isAllSelected(text)) {
            host.selectAll();
            resetSelection();
        } else if (inputHandler) {
            resetSelection(host.selection.isEmpty());
        }
    };
    

    【讨论】:

    • 要在缩小的 ace.js 中更新它,找到第一个出现的 E(n)(区分大小写)并将其替换为 n.value&&E(n)。 (非常感谢您的回答。)
    • 不应该已经将这个修复添加到官方 ace.js 代码中吗?这是 2017 年,错误仍然存​​在。感谢 DanielGabriel 和@mch 的回答
    • 感谢您的回答。当编辑器在表单中并且您调用 form.reset() 时会出现同样的问题
    【解决方案2】:

    这很可能是由渲染器中过时的缓存大小引起的。 显示模态后需要调用editor.resize()

    【讨论】:

    • 谢谢,这没有帮助。我用更多代码更新了我的问题 - 当显示模式时我确实调用了 resize() 。到那时,值已经设置,问题仍然存在。我尝试通过将此代码放在“显示”事件处理程序中来反转(调整大小,然后设置值):snippetEditor.resize(); snippetEditor.session.setValue(snippetEditor.session.getValue(), -1);,结果相同。
    • 您能否为该问题创建一个 jsbin 演示,或者将您的页面放在可见的地方,我无法使用您问题中的代码 sn-ps 重现该问题。
    • 这是一个 jsfiddle,但它没有重现问题:jsfiddle.net/daniel_gabriel/02t1wphe/2 我将继续调查。
    • 由于脚本 mime 类型问题,您的 jsfiddle 没有运行。我已将其更新为 jsfiddle.net/02t1wphe/8,但使用该版本我无法在 firefox 上重现该问题
    • 我无法在 jsfiddle 中重现这一点,但我认为还有其他事情发生。我更新了问题。
    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多