14

ユーザーが互いにメッセージを入力できるようになる、私の Web サイトで contentEditable 領域を開発しています。

<div contentEditable="true" class="smartText">User types here...</div>

つまり、ユーザー@usersameがこの div 内に入力@usernameすると、ユーザー名が存在する場合は青色で、存在しない場合は緑色で強調表示されます。そしてもちろん、これはすべてユーザーが入力するときに発生するはずです...

どこから始めればよいかわかりません。今のところ、これがあります。

$("body").on("keyup",".smartText",function(){
      var $this = $(this),
          value = $this.html(),
          regex = /[^>]#\S+[^ ]/gim;
      value = value.replace(regex,"<span style='color:red'>$&</span>");
      $this.html(value);
});

しかし、テキストは(キャレットの位置と同様に)ジャンプし続け、正しい方向のようには感じられません。コードを見つけたときに色を付ける JSFiddle に少し似ていると思います。私は基本的にTwitterと同じものを望んでいます。

ここで遊ぶための JSFiddle があります: http://jsfiddle.net/denislexic/bhu9N/4/

よろしくお願いします。

4

5 に答える 5

4

ユーザーが入力した HTML マークアップは、非常に驚​​くべきものである可能性があることに注意して<span>@use</span><span>rname</span>ください@username

contentEditable要素内でのクレイジーなキャレット動作 (およびその他の厄介な副作用) を回避するには、W3C DOM APIを使用して、HTML に変更があるたびに DOM ツリーをたどる必要があります (body.innerHTMLタイマーをポーリングすることで変更を検出できます)。

最近、CKEditorに関する同様の質問に回答し、テキストの一致を見つけるために、DOM のテキストからノードへのマップを作成する方法のアルゴリズムについて説明しました。CKEditor DOM APIは W3C のものと非常に似ており、同じアルゴリズムを適用できます。

一致が見つかったら、DOM Range APIを使用して DOM ノードのコンテンツを操作する必要があります。たとえば、一連のプレーン テキストをスタイル付きでラップするには<SPAN>:

var range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
var span = document.createElement("span");
span.style.backgroundColor = "blue"
range.surroundContents(span);

全体として、このタスクは非常に簡単ではなく、JavaScript コードの 1 ページに収まるものではありません。ここで回答します。

于 2014-01-29T10:38:09.807 に答える
2

これは、問題の解決策のようです。

デモはこちら: http://jsfiddle.net/bhu9N/5/

$(document).ready(function() {
    $("body").on("keyup", ".editable", function(e) {
        var $this = $(this);
        if(e.keyCode==32) {//space
            var words = $this.text().split(' ');
            var lastword = $.trim(words[words.length-1]);
            var reg = /^@\S+/;
            if(reg.test(lastword)) {
                //make an AJAX call for checking this word for existence
                //suppose data is returned and data==1 means green
                var data = 1;
                if(data==1) {
                    var orgtext = $this.html();
                    orgtext = orgtext.replace(lastword, '<span class="green">'+lastword+'</span>');
                    $this.html(orgtext);
                }
            }   
        }
    });

});​

テキストが強調表示されると、カーソルが div の先頭に移動します。したがって、これはまだ修正する必要があります。解決策が見つかったら更新します。その間、私が今提供したものを試してみて、それが役立つかどうかを確認してください.

于 2012-10-28T08:13:29.850 に答える
1

Ezos が彼の回答で指摘したように、ユーザーがキーを離すたびに集中的なこと (ユーザー名が存在するかどうかを確認するための Ajax リクエストを行うなど) を試みることはお勧めしません。あなたは悪い時間を過ごすかもしれません。そうは言っても、ユーザーが入力を停止してから一定時間待って、入力した内容を実行し、単語を強調表示することをお勧めします。次に例を示します。

var textarea = $(".smartText");
var highlightWords = function highlightWords() {
    var original = textarea.text();
    var replaced = original.replace(/@[a-zA-Z0-9]+/g, function (username) {
        // Magic
        return "<span class='exists'>" + username + "</span>";
    });
    textarea.html(replaced);
};
var timer;

textarea.keyup(function (e) {
    clearTimeout(timer);
    if ($(this).text()) {
        timer = setTimeout(highlightWords, 1000);
    }
});

フィドルへのリンク: http://jsfiddle.net/neJLW/

上記のコードで、正しい方向に進むことができると思います。あなたが言ったように、カーソルはまだ飛び回るので、の内容を編集するたびに保存して元の位置にリセットする必要がありますdiv。また、ユーザー名が存在するかどうかを判断するのにかかると予想される時間に応じて、タイムアウトを調整する必要があります。ユーザー名チェックに置き換え// Magic、それに応じて戻り値を調整する必要があります。

余談ですが、特定のものをspans でラップする際のアクセシビリティの問題に注意してください (例については、Lettering.js のこの GitHub の問題を参照してください)。

編集:これは堅牢なソリューションではないことにも注意してください(たとえば、コピーペーストには反応しません)。YMMV。

于 2014-01-29T01:48:24.507 に答える
0

あなたが使用している方法は非常にブラウザ集約的であり、誰かが非常に速く入力し、「文字列」が ajax を介して検証される前に複数の要求を実行している場合、問題が発生する可能性があります。http://aehlke.github.io/tag-it/などのライブラリを使用すると良いかもしれません- タグを推奨するのと同じように、フォントの色などを変更する関数を描くことができます。

時間があれば、フィドルのデモを作ります。

于 2014-01-29T00:36:55.730 に答える