3

HTMLドキュメントの編集可能な領域にコンテンツアシスタントの実行例を作成しました。したがって、ユーザーがキーボードのCtrlキーとスペースを押すと、コンテキストメニューが表示されます。現在(以下のデモを参照)、コンテキストメニューは正しいy位置にあります(テキストの下)。ただし、x軸には沿っていません(テキストが長くなると、行の先頭にボックスが表示されます)。

この問題を解決するのを手伝ってもらえますか?

ご挨拶、怪しい伝説

コード例:

<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Test</title>
<script type="text/javascript">

var iframe = null, iwindow = null, iDocument = null;

function setUpInput() {
        iframe = document.createElement( 'iframe' );
        iframe.setAttribute( 'id', 'iframe-test' );
        iframe.setAttribute( 'frameborder', 0 );
        iframe.setAttribute( 'style', 'width:100%; height:100%;border: solid 1px red;' );

        document.getElementById( "input" ).appendChild( iframe );

        iwindow   = iframe.contentWindow;
        idocument = iwindow.document;

        idocument.open();
        idocument.write("<p></p>");
        idocument.close();

        idocument.body.setAttribute( 'spellcheck', false );
        idocument.body.setAttribute( 'style', 'font-family: Consolas,serif;font-size: 0.8em;' );
        idocument.body.contentEditable = true;

        iwindow.onkeydown = function(e) {
            if (e.ctrlKey && e.keyCode == 32) {
                createSuggestObject();
                return false;
            }
            if (e.ctrlKey) return false;
        };

        iwindow.onkeypress = function(e) {if (e.ctrlKey) return false;};
}

function createSuggestObject() {
suggest = new Object();
suggest.box = document.createElement( 'div' );
suggest.box.style.position = 'absolute';
suggest.box.style.width = '120px';
suggest.box.style.overflow = 'auto';
suggest.box.style.border = '1px solid #BEC7E4';
suggest.box.style.display = 'block';
suggest.box.style.marginTop = '16px';
suggest.box.innerHTML = "Example 1";
document.body.appendChild( suggest.box )

var position = iframe.getBoundingClientRect();

var selObj = iwindow.getSelection();
var selRange = selObj.getRangeAt(0);
var p2 = selObj.anchorNode.parentNode.getBoundingClientRect();  

suggest.box.style.top = Math.round( window.scrollY + position.top + p2.top) + 'px';
suggest.box.style.left = Math.round( window.scrollX + position.left + p2.left) + 'px';

}

window.onload = function() {
    setUpInput();
};
</script>

</head>
<body>
<div id="input"></div>
</body>
</html>
4

1 に答える 1

0

ソリューションの主な問題は、提案オブジェクトを配置する場所への参照として、p要素の境界矩形(ユーザーが入力したテキストが含まれていると想定)を使用していたことでした。

まず、提案オブジェクトの位置に長方形の幅を制限することを考慮していなかったため、テキストの長さに関係なく、提案ボックスは左側にとどまりました。

ただし、テキストに複数の行がある場合(2番目の行が最初の行よりも短い場合)、境界矩形の幅は最初の行の長さと同じになるため(多かれ少なかれ)、このアプローチは最終的に失敗します。したがって、提案オブジェクトは正しく配置されません。

コードを修正する方法についての私の最初のアイデアは、テキストにインライン要素を追加し(必要に応じてビーコン)、その位置を測定し、DOMから削除し、その計算された位置を使用して提案オブジェクトを適切に設定することでした。

それはほとんど機能することが判明しました。ほとんどの場合、結局のところ、ブラウザが異なれば、contentEditableの行末を処理する方法も異なります。たとえば、Firefox<br _moz_dirty=""/>は行の最後に挿入しますが、Chromeは挿入しません。そのため、テキストの後にビーコン要素を追加しようとすると、その後に追加されたため、<br/>再び間違った位置になりました。

解決策は、処理しているテキストノードの取得方法を変更し、そのnextSiblingの直前にビーコンを挿入することでした。

これが実際の例ですhttp://jsfiddle.net/MmKXS/10/

注1:<p></p>Chromeではユーザーが入力したテキストが挿入されなかったため、iframeのドキュメントへの空の要素の追加を削除しました。これにより、提案オブジェクトの配置にさらに別の問題が発生します。

注2:今のところ、私のソリューションは、テキストの最後に提案オブジェクトを配置する場合にのみ機能します。textNodeの分割、ビーコンの挿入、位置の確認、textNodeの再度のマージが含まれるため、カーソル位置には機能しません。そのコードのユースケースによっては、パフォーマンスの低下につながる可能性があり、および/または提案オブジェクトの配置に対処する方法のアプローチ全体を変更する必要がある可能性があります。

于 2011-11-08T09:19:27.900 に答える