3

Javascript を学習するために、WYSIWYG コード エディターを実装しようとしています。content-editabledivやを実装する代わりにtextarea、私は Ajax.org の ACE の本から 1 枚 (というより、たくさんの 1 枚) を取り出しました。

すべての入力イベントを処理するために、0 に設定されdivたリスナーがあります。tabIndexテキスト領域、カーソル、ガターなど、エディターのすべてのコンポーネントは、このリスナーの子です。マウス イベント ハンドラーを実装して以来、イベントにフォーカスが失われるという問題がありましたmousedown。どうやら、リスナーでイベントが発生したblur場合でも、イベントが発生しています。mousedown

特定のメソッド呼び出しをコメントアウトし、問題の原因を正確に調べようとした後、原因はrenderメソッドにあることに気付きました。さて、このメソッドは入力ごとに呼び出すので、特にmousedownイベントで呼び出したときにフォーカスがずれてしまうのは非常に奇妙です。renderメソッドをコメントアウトすると、blurイベントがあるときにイベントが発生しませんmousedown

さらに進んでいくと、テキスト コンテナの を置き換えた部分をコメント アウトするとinnerHTML、問題が解消されることがわかりました。replaceInnerHTML関数内のさまざまな場所で関数を使用しているため、これも非常に奇妙ですrenderが、特にテキストを更新した場合にのみ問題が発生するようです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

要素にフォーカスを当てたいときは、そこにとどまっている要素をクリックする必要があるようです。それを別の要素に置き換えた場合、ブラウザは明らかにだまされてその要素にフォーカスすることはありません。

あなたができることは、ブラウザにマウスダウン/フォーカスなどのプロセスを終了させ、その後手動で要素にフォーカスさせることです。これはhttp://jsfiddle.net/wG4Yy/41/setTimeout(..., 0)の呼び出しで実現できます。

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