22

ユーザーがその中のテキストを更新できるようにするために、div でブラウザーの contenteditable=true を使用すると、(Chrome を使用して) この問題が発生します。

削除バックスペース キーを使用して改行を削除する (1 行上にジャンプする) 場合、ブラウザはそのテキストの周りにインライン スタイル セットのタグを挿入します。

それを行うだけでなく、そのスパンタグにインラインスタイルを追加するため、これは本当にイライラします。たとえば、フォントの色が現在黒の場合、そのスパンタグに style="color:black" を追加します。

その結果、インライン スタイルによってスパン タグに強く設定されているため、ツールバーでそのテキストの色を編集できなくなりました。これと同じことを削除キーで行をバックアップすると、フォントサイズでも同じことが起こります。

contenteditable について 1 つまたは 2 つのことを教えてくれる人、またはこのブラウザーの動作を防ぐことができない場合は、スパンを削除する方法を提案できる人..

** この問題を再現するには ** - ブラウザで div を作成し、たとえば font-size:36px でインライン スタイルを設定します - ブラウザで編集可能なコンテンツで div のテキストを編集し、手動で改行して数行を書き込みます。- テキストの段落の前 / 前にカーソルを置き、バックスペースを押します。カーソルの前にあるテキストの周りに span タグが生成され、スタイルが変更されます。

更新* * だから私はいくつかの異なる解決策を試しましたが、成功は限られていました。最初にすべてのタグを削除しようとしましたが、すべての改行も失いました (より良い正規表現でこれを解決できる可能性があります。私は正規表現の作成の専門家ではありません)。

以下のすべての関数は、最初にキーアップ イベントで呼び出されましたが、その後、テキスト ボックスの選択を解除するためにそれらをアタッチしました。以下の関数を起動する方法は、質問とは無関係です。

        //option to remove all tags
        var withTags = $(textObject).html();
        var withoutTags = withTags.replace(/<(?:.|\n)*?>/gm, '');       
        $(textObject).html(withoutTags);

私の2回目の試みは、テキストボックスの下にあるオブジェクトのスタイルタグを削除することでより成功しました(クロムが追加したテキストボックス内のdivとスパン)。これが私の最初のコードです

        //option to remove style of elements
        $(textObject).children().each(function() {
            $(this).removeAttr('style');
            console.log('removing style from first level element: '+this);

        });

次に、テキストボックスを編集するたびに、chrome が上記のコードでは届かない新しいネストされたレベルの div/span タグを追加する可能性があることに気付いたので、次のようにしました。

        //option to remove style of elements
        $(textObject).children().each(function() {
            $(this).removeAttr('style');
            console.log('removing style from first level element: '+this);

            //And of course it would be all too easy if chrome added only one level of elements...
            $(this).children().each(function() {
                $(this).removeAttr('style');
                console.log('removing style from second level element: '+this);
            });

        });

しかし、ネストの量は理論的には無制限になる可能性があるため、それだけでは十分ではありません。まだより良い解決策に取り組んでいます。どんな入力でも大歓迎です =)

4

5 に答える 5

6

問題は、実際には、スパンと p を挿入するだけでなく、たまたまテーブルをコピーすると、そこに tbody と行を含むテーブル全体が挿入されることです。したがって、これを処理するための唯一のオプションは、次のとおりです。

$(document).on("DOMNodeInserted", $.proxy(function (e) {
        if (e.target.parentNode.getAttribute("contenteditable") === "true") {
            with (e.target.parentNode) {
                replaceChild(e.target.firstChild, e.target);
                normalize();
            }
        }
}, this));

はい、全体的なページのパフォーマンスに多少影響しますが、テーブルやコンテンツを contenteditables に挿入することをブロックします。

更新:
上記のスクリプトは、必要なコンテンツが 1 レベルの span/p タグでラップされている場合の基本的なケースのみを処理します。ただし、たとえば Word からコピーすると、テーブル全体をコピーすることになる場合があります。したがって、これまでに投げたすべてを処理するコードは次のとおりです。

$(document).on("DOMNodeInserted", $.proxy(function (e) {
    if (e.target.parentNode.getAttribute("contenteditable") === "true") {
        var newTextNode = document.createTextNode("");
        function antiChrome(node) {
            if (node.nodeType == 3) {
                newTextNode.nodeValue += node.nodeValue.replace(/(\r\n|\n|\r)/gm, "")
            }
            else if (node.nodeType == 1 && node.childNodes) {
                    for (var i = 0; i < node.childNodes.length; ++i) {
                        antiChrome(node.childNodes[i]);
                    }
            }
        }
        antiChrome(e.target);

        e.target.parentNode.replaceChild(newTextNode, e.target);
    }
}, this));

また、あなたのケースで特に危険なシンボルを削除するために、好きな方法で正規表現を自由に変更してください。

UPDATE 2
少し考えてグーグルで調べた後、上記のコードを単純なjQueryプラグインにラップして、使用を容易にしました。ここにGitHubリンクがあります

于 2014-06-30T15:59:26.793 に答える
2

これが私がこれを解決した方法です

jqueryはコンテンツを保持しながら <span> タグを削除します(そして <divs> と <p>:s を <br> に置き換えます)

すべての div、span、および p タグのテキストを保持し、それらのタグを削除して、すべての div および p を br に置き換えます。私はぼかしでそれを行います。キーダウンごとに行うのが最適ですが、これらすべての%#¤¤% & (あなたが言った) ネストされた要素をループする必要があるため、CPU を使いすぎます。

于 2013-10-25T18:19:33.473 に答える
1

スタイルを追加 display:inline-block; contenteditable にすると、chrome で自動で div、p、span が生成されなくなります

于 2014-07-11T02:56:47.617 に答える
0

男、この質問のタイミングは狂っています。私が contenteditable でやっていることは、すべてのコンテンツを contenteditable div の段落タグ内に強制することです。

したがって、作成されたこのでたらめなスパンを処理する方法は<p>、すべてのキーストロークをフラット化することです。

.text()サブ要素を含む要素のすべてのテキストを選択するため、(coffeescript で) 設定するだけです。

t = $(element).text()
$(element).children().remove()
$(element).text(t)

これは私の問題を解決します。余談ですが、これらのブラウザーの実装者は contenteditable をかなりひどいものにしました。これは本当にウェブの未来なので、これを簡単にする大きなチャンスがあります。

于 2013-10-10T15:57:19.017 に答える