【JavaScript(HTML)】対応するカッコを強調表示する方法【テストツール】

JavaScript

はじめに

このカッコに対応するカッコはどこなのか。。

入力補助となり視認性も上がるため、対応するカッコを強調表示するJavaScript(HTML)を作りました。

カーソル位置に対応するカッコをグレーで表示

対応するカッコを強調表示するデモ

対応するカッコを強調表示するデモです。

以下テキストエリアのカッコの後ろへカーソルを当てると対応するカッコへ色を付けて表示(点滅)します。

【テキストエリア】
{“id”: 111, “products”: [ { “name”: “Coffee”, “quantity”: 1 } ] }

実装方法

テキストエリア内で対応するカッコを強調表示するJavaScript(HTML)を実装します。

以下のソースをコピーしテキストエディタへ貼付け、保存してください。(ファイル名は任意、拡張子は.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>【JavaScript(HTML)】テキストエリア内の対応するカッコを強調表示する方法【テストツール】</title>
    <!-- こちらのjqueryはバージョンアップ等、適宜変更してください -->
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script> 
  </head>
  <body>
    【テキストエリア】<BR>
    <textarea id="req_text" cols=120 rows=10>
{"id": 111,
  "products": [
                {
                  "name": "Coffee",
                  "quantity": 1
                }
              ]
}
</textarea>
    <div id="req_overlay" cols=120 rows=10>
{"id": 111,
  "products": [
                {
                  "name": "Coffee",
                  "quantity": 1
                }
              ]
}
    </div>
  </body>
</html>
<script type="text/javascript">
const textElem    = document.querySelector('#req_text');
const overlayArea = document.querySelector('#req_overlay');

//keyup時処理
textElem.addEventListener('keyup', (event) => {
  var txt = '\n' + event.target.value + '\n';
  txt= bracketBlink(txt);
  overlayArea.innerHTML = txt;
});

//click時処理
textElem.addEventListener('click', (event) => {
  var txt = '\n' + event.target.value + '\n';
  txt= bracketBlink(txt);
  overlayArea.innerHTML = txt;
});

//対応カッコ表示
function bracketBlink(text) {
    let txtArr = text.split('');
    let bct = bracketPut(text);
    var inx = bct.map(x=>x[0]).indexOf(textElem.selectionStart);
    if( inx >= 0 && bct[inx][1] !== ""){
        var str = bct.map(x=>x[1]).indexOf(bct[inx][1])
        var end = bct.map(x=>x[1]).lastIndexOf(bct[inx][1])
        txtArr[bct[str][0]] = `<span class='hLight'>` + txtArr[bct[str][0]] + `</span>`;
        txtArr[bct[end][0]] = `<span class='hLight'>` + txtArr[bct[end][0]] + `</span>`;
    }
    return txtArr.join("");
}

//カッコ格納
function bracketPut(text) {
    let putArr = [];
    let txtArr = text.split('');
    let bCnt = 0;
    for (let i = 0; i < txtArr.length; ++i) {
        switch (txtArr[i]) {
            case "{" :
                putArr.push([i,""]);
                break;
            case "}" :
                putArr.push([i,""]);
                var inx = bracketFind(putArr,putArr.length - 1);
                if (txtArr[inx[0]] == "{") {
                    putArr[inx[1]][1] = bCnt;
                    putArr[putArr.length - 1][1] = bCnt;
                    bCnt = bCnt + 1;
                }
                break;
            case "[" :
                putArr.push([i,""]);
                break;
            case "]" :
                putArr.push([i,""]);
                var inx = bracketFind(putArr,putArr.length - 1);
                if (txtArr[inx[0]] == "[") {
                    putArr[inx[1]][1] = bCnt;
                    putArr[putArr.length - 1][1] = bCnt;
                    bCnt = bCnt + 1;
                }
                break;
        }
    }
    return putArr;
}

//カッコindex検索
function bracketFind(arr,num) {
    for (let i = num; i--;) {
        if (arr[i][1] === ""){
            return [arr[i][0],i]
        }
    }
    return [-1,-1];
}

//テキストエリアサイズ変更対応
document.addEventListener('DOMContentLoaded', () => {
  const observer = new MutationObserver(() => {
    const width  = textElem.getBoundingClientRect().width
    const height = textElem.getBoundingClientRect().height
    overlayArea.style.width  = width + "px";
    overlayArea.style.height = height + "px";
  })
  observer.observe(textElem, {
    attriblutes: true,
    attributeFilter: ["style"]
  })
}, false)

//テキストエリア改行対応
$('#req_text').scroll(function() {
  var t = $(this).scrollTop();
  var l = $(this).scrollLeft();
  $('#req_overlay').scrollTop(t);
  $('#req_overlay').scrollLeft(l);
});
</script>
<style>
#req_text {
    background-color: transparent;
    padding: 13px 12px;
    position: absolute;
    overflow-wrap: break-word;
    margin: 2px;
    white-space: pre-wrap;
    font-family: monospace;
    font-size: 14px;
    width: 800px;
    height: 150px;
}
#req_overlay {
    color: #e2e2e2;
    padding: 1px 12px;
    overflow: hidden;
    overflow-wrap: break-word;
    margin: 2px;
    white-space: pre-wrap;
    font-family: monospace;
    font-size: 14px;
    width: 800px;
    height: 150px;
}
#req_overlay span.hLight {
  background: linear-gradient(transparent 0, #C0C0C0 0);
  -webkit-animation:blink 0.51s ease-in-out infinite alternate;
}
@-webkit-keyframes blink{
    0% {opacity:0;}
    100% {opacity:1;}
}
</style>

テキストエリアのサイズや位置は必要に応じて微調整してください。

※72-83行目:case “{” : ~中略~ break; の「{}」の部分を追加変更することで、「()」など別の文字括りにも対応できます。

便利な入力補助機能

テキストエリアへJSONデータを入力する際の入力補助機能を以下の記事で紹介しています。

解説

テキストエリアの下へdivタグを重ねています。

keyup・click時に、JavaScriptで対応するカッコをspanタグへ入れ、他の文字も含めてdivタグへ入れてます。

対応するカッコのspanタグへは、背景色付き・点滅のclassが設定されています。

対応するカッコの見分け方は、テキスト中のカッコを全て配列へ入れ、以下のようにカッコそれぞれの位置、グループを付けて検証しています。

index:147の「]」を削除した場合、配列は以下のように変わります。

カーソル位置を青いカッコ後ろへ置くと対応するカッコがあるので強調表示しますが、それ以外のカッコはグループとして認識していないので強調表示しません。

対応するカッコを強調表示するメリットは?

1. コードの可読性向上

  • 対応するカッコが強調表示されることで、コードの構造が視覚的に明確になり、どの部分がどのブロックに属しているかが一目でわかります。
  • 特にネストが深い場合や複雑なコードで、各ブロックの範囲を簡単に識別できるようになります。

2. エラーの早期発見

  • 強調表示により、対応するカッコが見つからない場合や誤ったカッコが使用されている場合に、すぐに気づくことができます。これにより、コードを実行する前にエラーを発見でき、デバッグ時間を短縮できます。

3. コーディングのスピードアップ

  • 対応するカッコが自動的に強調表示されることで、どこに閉じカッコを追加する必要があるかを考える時間が短縮され、コーディングがスムーズに進みます。
  • 特に長いコードや複雑な条件分岐・ループがある場合、強調表示が助けになります。

4. ネストの確認が容易

  • 複数の入れ子構造がある場合、強調表示されるカッコを追跡することで、どのカッコがどのブロックに対応しているのかを簡単に確認できます。
  • これにより、誤ってネストを閉じてしまうリスクを減らせます。

5. 他のコードと視覚的に区別

  • カッコを強調表示することで、他のコード(変数、演算子、文字列など)と視覚的に区別でき、カッコに関するミスを避けやすくなります。

6. コーディングスタイルの維持

  • 強調表示されたカッコを見ることで、規則正しいインデントやフォーマットを維持しやすくなります。これにより、コードのスタイルが統一され、読みやすさが向上します。

7. コードレビューの効率化

  • 他の開発者がコードレビューを行う際に、カッコが強調表示されていると、構造を理解しやすくなります。これにより、レビューの効率が上がり、ミスを見逃すリスクが減少します。

8. 教育や学習のサポート

  • プログラミング初心者にとって、カッコの使い方を理解するのは難しいことがあります。強調表示によって、どのカッコがどの部分に対応しているかが視覚的に分かりやすくなり、学習がスムーズに進みます。

これらのメリットにより、対応するカッコを強調表示することは、コードの正確性、可読性、そしてコーディング体験の向上に大きく寄与します。

まとめ

JavaScript(HTML)で対応するカッコを強調表示する方法を説明しました。

テキストエリア内の対応するカッコが判断出来て、入力補助にもなるのでオススメです。

コメント

タイトルとURLをコピーしました