web-dev-qa-db-ja.com

テキスト領域を部分的に編集可能にする方法はありますか? (テキストの一部のみを編集可能にします)

テキスト領域(以前はテキストがロードされていた)の一部のみを編集可能にし、他の部分は編集可能(いわば「グレー表示」)にするのがエレガントな解決策になる状況に遭遇しました。

これは一般的にJavaScriptを使用することで可能ですか?

私はjQueryを使用します。

20
Kenji Kina

あなたはこれを行うことができます(概要のアイデアだけで、コードはありません):

テキスト全体に一致する正規表現を考案します。変更不可能な部分には固定文字列を使用し、変更可能な部分には[\s\S]*?を使用します。 ^$を使用して、正規表現を固定します。

/^This is fixed text\. Now something editable:[\s\S]*?Now fixed again\.$/

ここで、keyupイベント、およびおそらく他のイベント(pasteなど)にも反応します。

関連するすべてのイベントで、正規表現がまだ一致しているかどうかを確認します。

そうでない場合は、イベントをキャンセルします。

事実上、これにより、正規表現でリテラルである部分への変更が停止され、テキストの特定の部分が読み取り専用になります。

フォームの投稿後にサーバー側でも文字列をテストすることを忘れないでください-クライアントが無効な値を送信できないことを決して信頼しないでください。


編集

正規表現の引用関数を使用して、文字列からその正規表現を動的に構築できます。これにより、面倒な作業を大幅に減らすことができます。

function regexQuote(s) { return s.replace(/[\[\]^$*+?{}.|\\]/g, "\\$&") }

使用法

var re = new Regex(
  "^" + 
  [regexQuote(fixedPart1), regexQuote(fixedPart2)].join("[\\s\\S].*?")
   + "$"
);
9
Tomalak

プレーンなtextarea要素を使用している場合、必要なコンテンツのスタイルを設定することはできません(そのコンテンツが編集可能かどうかに基づいて)。せいぜい、ユーザーが変更しようとしているコンテンツがブラックリストまたはホワイトリストのいずれかにあるかどうかを確認し、それに応じて編集を停止することができます。また、「それはできません」という警告メッセージなどの視覚的なフィードバックを提供することもできます。

contenteditable 属性を利用することをお勧めします。これは、スタイル設定に少し時間がかかる場合がありますが、長期的にははるかに高い柔軟性が得られます。

Div要素を必要なテキスト領域によく似たスタイルに設定し、その中で編集可能なスパンを使用して、特定のテキストブロックを編集できるかどうかを設定できます。次に、JavaScriptコマンド(上記のリンクを参照)を使用するか、「保存」ボタンを使用してこのコンテンツを取得し、実際のテキスト領域(非表示にした可能性があります)の値として設定し、通常どおりページを投稿します。

大まかな例として次のコードを使用します。

<div id="editable-content">
    <span id="block1" class="editable" contenteditable="true">This is some editable content which will </span>
    <span id="block2" class="non-editable">quickly be followed by some non-editable content</span>
</div>
<div style="display: none;">
    <textarea id="PostedContent"></textarea>
</div>
<div>
    <input id="save-page" type="submit" value="Save Page" />
</div>

<script type="text/javascript">
    $(function () {
        $('#save-page').click(function () {
            $('#PostedContent').val($('#editable-content').text());
        });
    });
</script>
9
Phil.Wheeler

さて、あなたはできたこのようなことをします。このコードは非常に非効率的です。私は概念の概要を説明しようとしています。

JS:

$(function () {
            var tb = $("#t").get(0);
            $("#t").keydown(function (event) {
                var start = tb.selectionStart;
                var end = tb.selectionEnd;
                var reg = new RegExp("(@{.+?})", "g");
                var amatch = null;
                while ((amatch = reg.exec(tb.value)) != null) {
                    var thisMatchStart = amatch.index;
                    var thisMatchEnd = amatch.index + amatch[0].length;
                    if (start <= thisMatchStart && end > thisMatchStart) {
                        event.preventDefault();
                        return false;
                    }
                    else if (start > thisMatchStart && start < thisMatchEnd) {
                        event.preventDefault();
                        return false;
                    }
                }
            });
        });

HTML

<textarea id="t" rows=5 cols="80">Hello this is a test @{stuff} 

        this part is editable @{other stuff}     

    </textarea>

これは「マーカー」のアイデアを使用しています。一般的な考え方は、「OK」と言うことです。ユーザーがマーカーの1つで編集しようとしているテキスト範囲はありますか?明らかに、キーが押されるたびに正規表現を使用することは、これを判断するための最良の方法ではありません。矢印キーなどを無視しているわけではありませんが、これは一般的な考え方です。

2
aquinas

興味深いアイデアですが、残念ながら、テキスト領域内のテキストは均一に処理する必要があります。つまり、テキスト領域のコンテンツのサブセクションを無効にすることはできません。

ただし、オプションはあります。無効にする必要のあるテキストを特定できる場合は、それをDOM要素(つまりdiv)として追加し、テキスト領域内にあることを意味するように配置できます。

このdivがテキスト領域内にあることを示すには、テキスト領域を大きくし、position:relative/absoluteスタイルを使用してdivをテキスト領域上に移動します。または、テキスト領域の境界線を削除して、「無効」テキスト付きのdivも含まれるコンテナに配置することもできます。

1
typeof

inputのコンテンツを編集可能/編集不可能なコンテンツのサブ文字列に分割するのではなく、HTML要素のcontentEditable属性を使用し、JavaScriptを使用することをお勧めします。その編集された値をページの他の場所の非表示のinputに渡します。

1
David Thomas

検索した後、テキスト領域を部分的に編集可能にするのは本当に難しいです

これが私がこの要件に使用した私のコードです

input
{
  width:100%;
  border:0px solid;
  outline:none
}

 
<!DOCTYPE html>
   <html>     
<div style="padding: 2px;border:1px solid #ccc;width: 82%;max-height:100px;min-height: 51px;overflow:auto;outline: none;resize: both;" contenteditable="true" unselectable="on">    
    

  <input placeholder="enter prefix..." value="editable postfix..." ></input>
  <div id='unEditable' style="background-color:yellow;width: fit-content;padding-left:10px;padding-right:10px;border-radius:10px;height: fit-content;" contenteditable="false" unselectable="off" onkeyup="" >
         fixed content non-editable
        
   </div>
  <input placeholder="enter postfix..." value="editable prefix..." style='width:97%'></input>
    
 </div>
</html>
1
Sunil Jakhar

親要素で、境界線を1pxの灰色の実線に設定し、この中に、

1)textarea(cssを変更して境界線を持たない)2)ラベル(境界線も持たない)

この場合、1)と2)の両方のテキストは、1つのボックスに配置されているため、一緒になっているように見えます。 1)もう一方はグレー表示されていますが、編集可能です。

0
Carmela

1つは読み取り専用でもう1つは編集可能な2つのテキスト領域を重ねて、1つだけのように見せることをお勧めします。