在努力学习Javascript的过程中,我一直在努力实现一个WYSIWYG代码编辑器。我没有实现内容可编辑的div
或textarea
,而是从Ajax.org的ACE书中抽出一片叶子(而不是很多叶子)。
我有一个监听器div
,tabIndex
设置为0,以处理所有输入事件。编辑器的所有组件(如文本区域,光标和装订线)都是此侦听器的子组件。自从实现鼠标事件处理程序以来,我一直遇到焦点在mousedown
事件上丢失的问题。显然,即使在侦听器中发生blur
事件,也会触发mousedown
事件。
在评论出某些方法调用并试图确切地看到导致问题的原因之后,我注意到罪魁祸首是render
方法。现在,我在每次输入后调用此方法,因此特别是当我为mousedown
事件调用它时,焦点丢失是非常奇怪的。在评论render
方法时,如果发生blur
事件,则不会触发mousedown
事件。
进一步说,事实证明,在评论我替换文本容器的innerHTML
的部分时,问题就会消失。这又是非常奇怪的,因为我在replaceInnerHTML
函数的不同位置使用render
函数,但问题似乎只是因为特别更新文本div
而出现。
这是replaceInnerHTML方法(我发现here):
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
安排更新,但两种尝试均无效。
我该怎么做才能解决这个问题?
答案 0 :(得分:1)
当你想要一个元素获得焦点时,你似乎必须点击一个留在那里的元素。如果你用另一个元素替换它,浏览器显然不会被欺骗聚焦那个元素。
您可以做的是让浏览器完成其mousedown / focus等过程,然后手动关注元素。这可以通过setTimeout(..., 0)
来电完成:http://jsfiddle.net/wG4Yy/41/。
setTimeout(function() {
wrapper.focus();
}, 0);