web-dev-qa-db-ja.com

ブラウザページで選択したテキストの座標

テキスト選択の先頭のピクセル単位の座標が必要です(textareaではなく、ページの任意の場所)。

カーソル座標を使用してみましたが、カーソル座標と選択範囲の先頭が必ずしも同じではないため(たとえば、ユーザーがテキスト上をドラッグしたとき)、これはうまく機能しませんでした。

私は誰かが解決策を持っていることを願っています!

32
Bouke

IE> = 9および非IEブラウザー(Firefox 4以降、WebKitブラウザーは2009年の初めからリリースされている、Opera 11、おそらくそれ以前))では、 getClientRects()Rangeのメソッド。IE 4-10では、boundingLeftと選択から抽出できるboundingTopTextRangeプロパティここに、最近のブラウザーで必要な機能を実行する関数を示します。

座標を誤って取得する場合があるいくつかの状況があることに注意してください0, 0、@ Louisによるコメントで言及されています。その場合、一時的に要素を挿入してその位置を取得するという回避策にフォールバックする必要があります。

jsFiddle: http://jsfiddle.net/NFJ9r/132/

コード:

function getSelectionCoords(win) {
    win = win || window;
    var doc = win.document;
    var sel = doc.selection, range, rects, rect;
    var x = 0, y = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            range.collapse(true);
            x = range.boundingLeft;
            y = range.boundingTop;
        }
    } else if (win.getSelection) {
        sel = win.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getClientRects) {
                range.collapse(true);
                rects = range.getClientRects();
                if (rects.length > 0) {
                    rect = rects[0];
                }
                x = rect.left;
                y = rect.top;
            }
            // Fall back to inserting a temporary element
            if (x == 0 && y == 0) {
                var span = doc.createElement("span");
                if (span.getClientRects) {
                    // Ensure span has dimensions and position by
                    // adding a zero-width space character
                    span.appendChild( doc.createTextNode("\u200b") );
                    range.insertNode(span);
                    rect = span.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                    var spanParent = span.parentNode;
                    spanParent.removeChild(span);

                    // Glue any broken text nodes back together
                    spanParent.normalize();
                }
            }
        }
    }
    return { x: x, y: y };
}

[〜#〜]更新[〜#〜]

コメントの結果としてWebKitバグを提出しましたが、修正されました。

https://bugs.webkit.org/show_bug.cgi?id=65324

56
Tim Down

キャレットが空の要素にある場合、TimDownによる上記の回答は機能しません。

以下のコードは問題を解決します。このコードはrange.getClientRects()を呼び出す前にrange.getClientRects()[0]配列がlength>0をチェックすることを除いて、TimDownのソリューションとほとんど同じであることに注意してください。

function getSelectionCoords() {
    var sel = document.selection, range, rect;
    var x = 0, y = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            range.collapse(true);
            x = range.boundingLeft;
            y = range.boundingTop;
        }
    } else if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getClientRects) {
                range.collapse(true);
                if (range.getClientRects().length>0){
                    rect = range.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                }
            }
            // Fall back to inserting a temporary element
            if (x == 0 && y == 0) {
                var span = document.createElement("span");
                if (span.getClientRects) {
                    // Ensure span has dimensions and position by
                    // adding a zero-width space character
                    span.appendChild( document.createTextNode("\u200b") );
                    range.insertNode(span);
                    rect = span.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                    var spanParent = span.parentNode;
                    spanParent.removeChild(span);

                    // Glue any broken text nodes back together
                    spanParent.normalize();
                }
            }
        }
    }
    return { x: x, y: y };
}
17
Jakobovski