web-dev-qa-db-ja.com

jQueryで改行を検出していますか?

新しい行の先頭の前にDOM要素を挿入するために、jQuery/javascriptに(CSS幅の制約に合わせるために)文字列が壊れている場所を検出させることは可能ですか?

24
Mild Fuzz

私はアプローチを考え出しましたが、それはあなたの目的にとってやり過ぎかもしれませんので、これを考慮に入れてください。

要素のクローンを作成し、元の要素を空にし、各Wordを元の要素に戻す必要があります。高さがいずれかの点で変化する場合、そのWordの前に改行があります。これは$(el).text()を使用して実行するのはかなり簡単ですが、テキストだけでなく他のタグを含めることができる場合はさらに複雑になります。この回答ボックスでノードごとに分解する方法を説明してみましたが、jsFiddleでjQueryプラグインを作成する方が簡単であることがわかりました。ここにリンク: http://jsfiddle.net/nathan/qkmse/Gist )。

フローティングエレメントはそれほどうまく処理されません。また、他にもいくつかの状況が発生して倒れる可能性があります。さらに多くのオプションが必要な場合、または目的に対して十分に機能しない場合、または適用方法がわからない場合は、私がお手伝いします。

38
Nathan MacInnes

これが1つのアプローチです。注:モノスペースフォントを使用しないと、理想的なソリューションはありません。等しい文字を使用すると、この作業がはるかに簡単になります。

  1. 等幅文字
  2. 1文字のサイズを計算する
  3. コンテナーのサイズを計算する
  4. 行ごとに文字を検索する
  5. 行が分割される場所(空白、ダッシュなど)を見つける
  6. すべての破壊インデックスを取得します。

関連するhtmlのjsfiddleを見てください。この機能はまだ完了していません。破壊指数を計算するときは、さらにチェックを入れる必要があります。現在、lastIndexOf( '')を使用していますが、次のインデックスがスペースまたは現在のインデックスである可能性があることは無視されます。また、他の改行文字については考慮していません。しかし、これは素晴らしい出発点になるはずです。

var text = $('#text').text(),                   // "lorem ipsum ... "
    len = text.length,                          // total chars
    width = $('#text').width(),                 // container width
    span = $('<span />').append('a').appendTo('#sandbox'),
    charWidth = span.width(),                  // add single character to span and test width
    charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row

var breakingIndexes = [], // will contain indexes of all soft-breaks
    gRowStart = 0,        // global row start index
    gRowEnd = charsPerRow;// global row end index

while(gRowEnd < len){
    var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
    breakingIndexes.Push(gRowStart + rowEnd); // add breaking index to array
    gRowStart = gRowStart + rowEnd + 1; // next start is the next char
    gRowEnd = gRowStart + charsPerRow;  // global end inxex is start + charsperrow
}

var text2 = $('#text2').text();           // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
    newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
    start = breakingIndexes[i]; // update start
}

$('#text2').html(newText); // output with breaks

http://jsfiddle.net/Y5Ftn/1/

6
Josiah Ruddell

これはテキストを受け取り、各行をスパンにする私のスクリプトです

CSS:

    margin: 0;
        padding: 0;
    }

    .title{
        width: 300px;
        background-color: rgba(233,233,233,0.5);
        line-height: 20px;
    }

    span{
        color: white;
        background-color: red;
        display: inline-block;
        font-size: 30px;
    }

    a{
        text-decoration: none;
        color: black;
    }

html

<div class="title">
        <a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
    </div>

JS

$(function(){

        $(".title").find("a").each(function(){

            var $this = $(this);
            var originalText = $this.text();
            $this.empty();

            var sections = [];

            $.each( originalText.split(" "), function(){
                var $span = $("<span>" + this + "</span>");
                $this.append($span);

                var index = $span.position().top;

                if( sections[index] === undefined ){
                    sections[index] = "";
                }

                sections[index] += $span.text() + " ";
            });

            $this.empty();

            for(var i = 0; i< sections.length; i++){
                if( sections[i] !== undefined ){
                    var spanText = $.trim(sections[i]);                     
                    $this.append("<span>" + spanText + "</span>");
                }
            }

        });

    });

JQueryを含める必要があります。

5

これを実行するためのjavascript関数の組み込みjQueryについては知りません。ただし、自分で行うことはできますが、テキストが多い場合は遅くなる可能性があります。

理論的には、高さが自動に設定されていることを確認し、テキストを削除してから、Word by Wordを再挿入できます。高さを変更したら、最後のWordを削除して、dom要素を挿入します。繰り返しますが、これは多くのテキストがある場合は遅くなります。これを行うためのより良い方法は、元の要素を変更せず、非表示にできる別の要素でそれを実行し、完了時に元の要素を置き換えることです。そうすれば、ユーザーはコンテンツが消えて、Wordごとに戻ってくるのを目にすることはありません。

もう1つの方法は、同様の原則を使用し、高さをautoにして同じサイズの空の要素から開始し、新しい行が表示されるまで新しい文字とスペースを挿入することです。そこから、上記の手法でこれを近似値として使用するか、dom要素の幅を考慮して、新しい行が見つかるまで各文字列の長さを盲目的に加算することができます。ただし、この手法は等幅フォントでより効果的に機能します。モノスペースフォントでは、近似としてのみ使用します。

とはいえ、キャンバスを使用してテキストを測定する方法はありますが、極端な場合があります。理論的には、canvas要素を作成し、コンテキストを取得し、すべてのフォントプロパティを設定してから、context.measureText()メソッドを使用します。その使用例は here にあります。

0
LoveAndCoding

または、テキストブロックの幅を親の幅と比較することもできます。ブロックが親の幅の98%以上である場合は、ブロックが壊れていることを確認してください

0
Harijs Deksnis

私は正規表現を使用して検出する方が簡単だと思います-効率を維持しながらコードをはるかに少なくします。

これは私のために働いたものです:

if ((/(\r\n|\n|\r)/.test($(this).val()))) {
    alert('there are line breaks here')
}

これが壊れた文字列で機能するかどうかはわかりませんが、jQueryで改行を検出するために機能します。

0
streetlight

あなたのユースケースが正確に何であるかはわかりませんが、 http://code.google.com/p/hyphenator/ が問題の解決策になるか、hyphenator.jsソースコードを掘り下げると、あなたが探しているコードを見つけることができるかもしれません。

0
Josh Schumacher