簡體   English   中英

“智能”文本區域自動縮進

[英]“Smart” text area auto indent

我正在嘗試創建一個自動縮進文本區域,到目前為止它使用以下代碼。 我遇到的問題是我目前正在阻止按Enter鍵的默認操作,以便計算行中的選項卡,然后插入換行符。

這有效,但我希望得到textarea的默認動作,因為如果按住enter鍵,它不會滾動textarea直到插入符號觸及底行,然后滾動條在底行保留插入符號。 如果在textarea的任何地方使用,下面的當前代碼將插入符號保持在視野范圍內,但它會使插入符號上方的內容向上滾動,這是一種妥協,因為插入符號不再消失。 如果沒有其他解決方案,這將工作正常,但我希望還有其他想法。

    var start = this.selectionStart-1;
    var end = this.selectionEnd;
    var sT = this.scrollTop;
    var sH = this.scrollHeight;
    var vH = $(this).height();

    var x = (sH - sT) - vH;

    // Check if hitting enter on the first line as no newline will be found
    if (this.value.lastIndexOf('\n',start)==-1)
     var startSubstr = 0;
    else 
     var startSubstr = this.value.lastIndexOf('\n',start)+1;

    var endFirst = end - startSubstr;

    var valueToScan = this.value.substr(startSubstr,endFirst);
    var count = 0;

    // Count only \t at the beginning of the line, none in the code   
    while (valueToScan.indexOf('\t')!=-1) {
     if (valueToScan.indexOf('\t')!=0)
      break;
     count++;
     valueToScan = valueToScan.substr(valueToScan.indexOf('\t')+1);
    }

    // Command to isert the newline, and then add the \t's found in previously  
    $(this).insertAtCaret('\n');
    for (var i=0;i<count;count--) {
     $(this).insertAtCaret('\t');
    }  

    var sH = this.scrollHeight;
    this.scrollTop = (sH - x) - vH;

編輯作為更新,為了消除任何混淆,我正在嘗試創建一個IDE樣式的文本框,例如在大多數IDE中,如果您鍵入以下內容

function example(whatever) {
     Example Stuff // And then hit enter here

我希望它能夠將您帶到左邊框的相同標簽距離作為“示例資料”,以便讓您的代碼更易於閱讀。 我目前有這個功能,但問題是我正在攔截回車鍵,這意味着我必須提供該功能。 我很難復制不滾動文本框的確切功能,直到光標到達底部邊框。 因此,如果你要在textarea的頂部按住enter鍵,光標就會向下滾動textarea,用它移動任何文本直到它到達底部邊框,然后textarea的滾動條將跟隨光標。 合理?

編輯2 更新了標簽,表明代碼是用PHP

這篇文章一直坐着,我一直在努力。 我認為當我有機會時我要探索的另一個選擇是阻止輸入只允許默認操作命中輸入並從lastIndexOf('\\n')-1讀取字符串到最近的\\n for任何\\t 我想這會給我一些我正在尋找的字符串,但不會弄亂textarea的行為。 測試后會再次更新。

編輯3已解決,根據我之前的更新,我決定在按下按鍵后掃描字符串,保留自然行為(下面為感興趣的人添加了更改的部分),唯一的問題是,如果你按住回車,它贏了不計算輸入印刷機原點的縮進,這對我來說很好。 我打算把這個給http://stackoverflow.com/users/15066/matyr'>matyr,雖然我在他回答之前確實弄清楚他仍然是最接近的。

if (this.value.lastIndexOf('\n',start-2)==-1) {
 var startSubstr = 0;
} else {
 var startSubstr = this.value.lastIndexOf('\n',start-1)+1;
}    
var valueToScan = this.value.substr(startSubstr,start);

我想要textarea的默認操作

如何綁定到keyup而不是keydown / keypress並在本機換行后插入選項卡?

滾動條在底行留下插入符號

您可以通過恢復scrollTop來保留滾動位置。

<!DOCTYPE html>
<title>autoindent example</title>
<textarea id="TA" rows="8"></textarea>
<script>
document.getElementById('TA').addEventListener('keyup', function(v){
  if(v.keyCode != 13 || v.shiftKey || v.ctrlKey || v.altKey || v.metaKey)
    return;
  var val = this.value, pos = this.selectionStart;
  var line = val.slice(val.lastIndexOf('\n', pos - 2) + 1, pos - 1);
  var indent = /^\s*/.exec(line)[0];
  if(!indent) return;
  var st = this.scrollTop;
  this.value = val.slice(0, pos) + indent + val.slice(this.selectionEnd);
  this.selectionStart = this.selectionEnd = pos + indent.length;
  this.scrollTop = st;
}, false);
</script>
<p>(not considering IE here)

你有沒有注意到Stack Overflow textareas如何處理代碼? 如果輸入:

function example(whatever) {
    Example Stuff // And then hit enter here
}

起初,什么都不會發生。 然后,當您縮進(通過鍵入或單擊101010按鈕)時,它會在代碼上添加不同的背景。 然后 ,等待一會兒后,語法會為代碼着色。 但如果你再次開始打字,它會回到黑/白。

我認為類似的方法可能對你有用。 您應該做的是:而不是嘗試將所有內容與enter keypress事件聯系起來。

  1. 連接正常的onKeySomething事件,但不要只查找“輸入”; 每次按鍵后:

    1A。 將一些全局變量(例如,計時器)設置為新的Date();

    1B。 setTimeout(X,timeoutFunction)其中X在用戶停止輸入后要等待很長時間

  2. 創建timeoutFunction; 這個函數應檢查全局“timer”變量,如果新的Date() - timer> X觸發actualFunction()

  3. 然后,actualFunction可以解析textarea的內容,縮進你喜歡的東西,沒有任何東西會中斷用戶的正常流程

我知道這不是“真正的”IDE的行為,但考慮到JS和網絡的局限性,它可能是最好的方法。

如何對文本框進行子類化並手動處理WndProc? 這樣可以獲得更細粒度的控制,並且可以解決類型鍵重復(KeyPress和類似事件僅在您按住鍵時觸發一次)。

public class MyTextBox : System.Windows.Forms.TextBox
{
    protected override void WndProc(ref Message m)
    {
        // Let the O/S handle the key first
        base.WndProc(ref m);

        // Then, if it's the return key, append tabs
        int numTabs = 3;                 // TODO: insert your own value here
        const int WM_CHAR = 0x0102;
        if(m.Msg == WM_CHAR && (char)m.WParam == '\r')
        {
            m.WParam = new IntPtr('\t'); // Recycle m since base is done with it
            for (int i = 0; i < numTabs; i++)
                WndProc(ref m);
        }
    }
}

我知道這不是一個直接的答案,但是你可以看到網上有一些例子可以幫助你實現這個。

http://jsfiddle.net
http://teddevito.com/demos/textarea.html
http://thelackthereof.org/JQuery_Autoindent

如果我有更多的時間,我肯定會試一試,但遺憾的是我沒有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM