在我学习Javascript的过程中,我试图实现一个所见即所得的代码编辑器。但我并没有像普通人那样用content-editable的div或textarea, 我参考了Ajax.org的ACE的做法。
我创建了一个listener div,并设置tabIndex为0来处理所有的输入事件。所有编辑器的组件,如文本区域、光标和侧边栏都是该listener的子节点。由于我实现了鼠标事件处理程序,我一直存在一个问题:当mousedown事件在listener上发生时,焦点会丢失。显然,即使mousedown事件在listener中发生,blur事件也会被触发。
经过注释某些方法调用并尝试确定问题的真正原因后,我发现罪魁祸首是render方法。现在,我在每次输入之后调用此方法,因此在调用它进行mousedow n事件时,焦点丢失非常奇怪。如果注释掉render方法,则在mousedown事件时不会触发blur事件。
进一步研究发现,注释掉替换text container的innerHTML部分后,问题就消失了。这又是非常奇怪的,因为我在render函数中的多个地方都使用了replaceInnerHTML函数,但似乎只有特别更新文本div时才会出现问题。
以下是我发现的replaceInnerHTML方法(可在http://blog.stevenlevithan.com/archives/faster-than-innerhtml查看)。
为什么仅仅替换特定节点的innerHTML会导致焦点模糊,而且只有在mousedown事件的情况下才会出现这种情况?或者说我错了方向,这个问题是由其他原因引起的吗?
编辑:感谢pimvdb,这里有一个重现问题的fiddle。blur事件似乎是由于在mousedown事件上重新构造节点而触发的。我不知道该如何解决这个问题。我已经尝试使用文档片段代替innerHTML,并尝试使用setTimeout调度更新,但两者都没有成功。我应该怎么做才能解决这个问题?
我创建了一个listener div,并设置tabIndex为0来处理所有的输入事件。所有编辑器的组件,如文本区域、光标和侧边栏都是该listener的子节点。由于我实现了鼠标事件处理程序,我一直存在一个问题:当mousedown事件在listener上发生时,焦点会丢失。显然,即使mousedown事件在listener中发生,blur事件也会被触发。
经过注释某些方法调用并尝试确定问题的真正原因后,我发现罪魁祸首是render方法。现在,我在每次输入之后调用此方法,因此在调用它进行mousedow n事件时,焦点丢失非常奇怪。如果注释掉render方法,则在mousedown事件时不会触发blur事件。
进一步研究发现,注释掉替换text container的innerHTML部分后,问题就消失了。这又是非常奇怪的,因为我在render函数中的多个地方都使用了replaceInnerHTML函数,但似乎只有特别更新文本div时才会出现问题。
以下是我发现的replaceInnerHTML方法(可在http://blog.stevenlevithan.com/archives/faster-than-innerhtml查看)。
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,这里有一个重现问题的fiddle。blur事件似乎是由于在mousedown事件上重新构造节点而触发的。我不知道该如何解决这个问题。我已经尝试使用文档片段代替innerHTML,并尝试使用setTimeout调度更新,但两者都没有成功。我应该怎么做才能解决这个问题?
mousedown
,就会触发blur
,键盘事件将不再起作用。) - RikonatorsetTimeout
来调用TextLayer.update
。像这样:http://jsfiddle.net/wG4Yy/42/. 它可以起作用,但正如你所说,感觉是一种弱解决方案。尽管如此,它仍然可以工作,我真的很感激。你能把它发布为答案而不是评论吗?这样我就可以接受它了。再次感谢! - Rikonator