3

在我努力学习 Javascript 的过程中,我一直在尝试实现一个所见即所得的代码编辑器。我没有实现 content-editablediv或 a textarea,而是从 Ajax.org 的 ACE 书中取出一片(相当多的一片)。

我有一个设置为 0 的侦听divtabIndex来处理所有输入事件。编辑器的所有组件,如文本区域、光标和装订线,都是此侦听器的子项。自从实现鼠标事件处理程序以来,我一直有一个问题是焦点丢失在mousedown事件上。显然,blur即使mousedown事件发生在侦听器中,事件也会被触发。

在注释掉某些方法调用并试图查看导致问题的确切原因后,我注意到罪魁祸首是render方法。现在,我在每次输入后调用这个方法,所以焦点丢失很奇怪,特别是当我为mousedown事件调用它时。在注释掉该render方法blur时,有事件时不会触发mousedown事件。

更进一步,事实证明,在注释掉我替换innerHTML文本容器的部分时,问题就消失了。同样,这很奇怪,因为我在replaceInnerHTML函数的各个位置都使用了该render函数,但问题似乎仅来自于特别更新 text div

这是 replaceInnerHTML 方法(我在这里发现的):

function replaceInnerHTML(el, html) {
    var newEl = el.cloneNode(false);

    newEl.innerHTML = html;

    el.parentNode.replaceChild(newEl, el);

    return newEl;
}

这是文本层的更新功能,省略不会出现此问题:

TextLayer.prototype.update = function(config) {
    html = [];

    var top = config.topRow;
    var last = config.lastRow;

    for(var i=top; i<=last; i++) {
        var line = this._session.getLine(i);
        if(line) {
            html.push('<div class="line" style="height:'+this.$characterSize.height+'px;">');
            this.renderLine(html, line);
            html.push('</div>');
        }       
    }   

    this._text = replaceInnerHTML(this._text, html.join(''));
    this.setSize(config.totalWidth, config.scrollHeight);
};

为什么焦点会因为替换innerHTML特定节点而变得模糊,而且只有在发生事件时才调用它mousedown

或者我在尝试调试时是否朝着完全错误的方向前进,而这个问题是由其他原因引起的?

编辑:

感谢 pimvdb,这里有一个重现问题的小提琴。http://jsfiddle.net/wG4Yy/39/

由于重组了事件上的节点,该blur事件似乎触发了mousedown。我不知道如何解决问题。我尝试过使用文档片段而不是 innerHTML,并且我也尝试过使用 安排更新setTimeout,但都没有成功。

我应该怎么做才能解决问题?

4

1 回答 1

1

当您想要一个元素获得焦点时,似乎您必须单击一个停留在那里的元素。如果你用另一个元素替换它,浏览器显然不会被欺骗来关注那个元素。

您可以做的是让浏览器完成其鼠标按下/聚焦等过程,然后手动聚焦元素。这可以通过setTimeout(..., 0)调用来完成:http: //jsfiddle.net/wG4Yy/41/

setTimeout(function() {
    wrapper.focus();
}, 0);
于 2012-08-19T18:10:29.797 回答