2012-02-07 18 views
15

テキストエリア内のカーソルの「行番号」(行)を調べて追跡したいと思います。 (より大きな画像は、もちろん、テキストが貼り付けられていない場合は、改行/改変/選択が行われるたびに行のテキストを解析することです。テキストエリア内のカーソルの行(行)番号を調べる

StackOverflowにはいくつかの投稿がありますが、特に私の質問には答えられません。ほとんどの質問は、ピクセル単位のカーソル位置、またはテキストエリア以外の行番号の表示です。

私の試行は以下の通りです.1行目から開始し、テキストエリアを終了しないとうまくいきます。テキストエリアをクリックして別の行に戻すと失敗します。開始行が1でないため、テキストを貼り付けるときにも失敗します。

JavaScriptの知識はかなり限られています。

<html> 

<head> 
<title>DEVBug</title> 

<script type="text/javascript"> 

    var total_lines = 1; // total lines 
    var current_line = 1; // current line 
    var old_line_count; 

    // main editor function 
    function code(e) { 

     // declare some needed vars 
     var keypress_code = e.keyCode; // key press 
     var editor = document.getElementById('editor'); // the editor textarea 
     var source_code = editor.value; // contents of the editor 

     // work out how many lines we have used in total  
      var lines = source_code.split("\n"); 
      var total_lines = lines.length; 

    // do stuff on key presses 
    if (keypress_code == '13') { // Enter 
     current_line += 1; 
    } else if (keypress_code == '8') { // Backspace 
     if (old_line_count > total_lines) { current_line -= 1; } 
    } else if (keypress_code == '38') { // Up 
     if (total_lines > 1 && current_line > 1) { current_line -= 1; } 
    } else if (keypress_code == '40') { // Down 
     if (total_lines > 1 && current_line < total_lines) { current_line += 1; } 
    } else { 
     //document.getElementById('keycodes').innerHTML += keypress_code; 
    } 

    // for some reason chrome doesn't enter a newline char on enter 
    // you have to press enter and then an additional key for \n to appear 
    // making the total_lines counter lag. 
    if (total_lines < current_line) { total_lines += 1 }; 

    // putput the data 
    document.getElementById('total_lines').innerHTML = "Total lines: " + total_lines; 
    document.getElementById('current_line').innerHTML = "Current line: " + current_line; 

    // save the old line count for comparison on next run 
    old_line_count = total_lines; 

} 

</script> 

</head> 

<body> 

<textarea id="editor" rows="30" cols="100" value="" onkeydown="code(event)"></textarea> 
<div id="total_lines"></div> 
<div id="current_line"></div> 

</body> 

</html> 
+1

、あなたは行意味ですか?テキストを書くとき、列と行は同じではありません。モノスペースでないフォントが使用されている場合、列はありません。 – Anurag

+0

申し訳ありません、はい、私は行を意味します。元の投稿を更新します。 – ethicalhack3r

答えて

23

selectionStartを使用します。

<textarea onkeyup="getLineNumber(this, document.getElementById('lineNo'));" onmouseup="this.onkeyup();"></textarea> 
<div id="lineNo"></div> 

<script> 

    function getLineNumber(textarea, indicator) { 

     indicator.innerHTML = textarea.value.substr(0, textarea.selectionStart).split("\n").length; 
    } 

</script> 

これは、マウスを使用してカーソル位置を変更した場合にも機能します。

+0

WOW。より良い解決策を求めることができませんでした!清潔で完璧に動作します!どうもありがとうございました! – ethicalhack3r

+0

あなたは大歓迎です:) – caleb

+18

テキストエリアにソフトラインブレークがある場合、この解決策は機能しません。 例:10の列を持つテキストエリアを作成し、そこに2つの単語を入れて、テキストが2〜3行にオーバーフローするようにします。ただし、改行を追加しないでください。上記のコードは、テキストエリアに "\ n"文字がないため、常に1を返しますが、実際には1行以上が表示されます。 これはTEXTAREAsの本当の難しさです...私は、現代のブラウザではこのための標準APIがないことに本当に驚いています... –

16

これは単語の折り返しのために厳しいです。改行の数を数えるのは非常に簡単ですが、改行のために新しい行があるとどうなりますか?この問題を解決するには、ミラーを作成すると便利です(クレジット:github.com/jevin)。ここでアイデアです:

  1. は、現在の行を抽出するために、ミラー
  2. 利用ミラーの高さにカーソルをテキストエリアの最初からコンテンツを送信するテキストエリア
  3. のミラーを作成します
  4. 線で

On JSFiddle

jQuery.fn.trackRows = function() { 
    return this.each(function() { 

    var ininitalHeight, currentRow, firstIteration = true; 

    var createMirror = function(textarea) { 
     jQuery(textarea).after('<div class="autogrow-textarea-mirror"></div>'); 
     return jQuery(textarea).next('.autogrow-textarea-mirror')[0]; 
    } 

    var sendContentToMirror = function (textarea) { 
     mirror.innerHTML = String(textarea.value.substring(0,textarea.selectionStart-1)).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br />') + '.<br/>.'; 
     calculateRowNumber(); 
    } 

    var growTextarea = function() { 
     sendContentToMirror(this); 
    } 

    var calculateRowNumber = function() { 
     if(firstIteration){ 
      ininitalHeight = $(mirror).height(); 
      currentHeight = ininitalHeight; 
      firstIteration = false; 
     } else { 
      currentHeight = $(mirror).height(); 
     } 
     // Assume that textarea.rows = 2 initially 
     currentRow = currentHeight/(ininitalHeight/2) - 1; 
     //remove tracker in production 
     $('.tracker').html('Current row: ' + currentRow); 
    } 

    // Create a mirror 
    var mirror = createMirror(this); 

    // Style the mirror 
    mirror.style.display = 'none'; 
    mirror.style.wordWrap = 'break-word'; 
    mirror.style.whiteSpace = 'normal'; 
    mirror.style.padding = jQuery(this).css('padding'); 
    mirror.style.width = jQuery(this).css('width'); 
    mirror.style.fontFamily = jQuery(this).css('font-family'); 
    mirror.style.fontSize = jQuery(this).css('font-size'); 
    mirror.style.lineHeight = jQuery(this).css('line-height'); 

    // Style the textarea 
    this.style.overflow = "hidden"; 
    this.style.minHeight = this.rows+"em"; 

    var ininitalHeight = $(mirror).height(); 

    // Bind the textarea's event 
    this.onkeyup = growTextarea; 

    // Fire the event for text already present 
    // sendContentToMirror(this); 

    }); 
}; 

$(function(){ 
    $('textarea').trackRows(); 
}); 
+2

これは受け入れられた答えである必要があります。私はコードをテストしていませんが、少なくともソフトの改行を処理する実用的なソリューションを試しています。 – ryandlf

+0

スタイリングはソリューションの必須部分ですか?私はこれをCSSなしで実装し、テキストエリアの折り返しプロパティを 'off'に設定しました。テキストエリアにテキストを入力すると(テキストスクロールバーが表示されます)、新しい行を作成していないにもかかわらず行番号レポートが増加します。 – youcantryreachingme

関連する問題