web-dev-qa-db-ja.com

テキストの真ん中の省略記号(Macスタイル)

Ellipsis("...")サイズ変更可能な要素内のテキストの中央。 ここ は次のようになります。そう、

"Lorem ipsum dolor sit amet. Ut ornare dignissim ligula sed commodo."

なる

"Lorem ipsum dolor sit amet ... commodo."

要素がテキストの幅まで引き伸ばされると、省略記号が消えます。これはどのように行うことができますか?

42
user102465

HTMLでは、次のように完全な値をカスタムdata- *属性に入れます。

<span data-original="your string here"></span>

次に、loadおよびresizeイベントリスナーをJavaScript関数に割り当てて、元のデータ属性を読み取り、それをスパンタグのinnerHTMLに配置します。 Ellipsis関数の例を次に示します。

function start_and_end(str) {
  if (str.length > 35) {
    return str.substr(0, 20) + '...' + str.substr(str.length-10, str.length);
  }
  return str;
}

異なるオブジェクトに必要な場合は、値を調整するか、可能であれば動的にします。異なるブラウザのユーザーがいる場合、DOMの他の場所で同じフォントとサイズでテキストから参照幅を盗むことができます。次に、使用する適切な文字数に補間します。

ヒントは、...またはwhoメッセージにabbr-tagを付けて、ユーザーが完全な文字列のツールチップを取得できるようにすることです。

<abbr title="simple tool tip">something</abbr>
29

この問題を解決する私の例を提案したいと思います。

主なアイデアは、テキストを2つの偶数部分に分割することです(または長さが奇数の場合は最初に大きくなります)。一方は最後に省略記号があり、もう一方はtext-overflow: clipで右揃えされます。

したがって、jsを自動/ユニバーサルにしたい場合、jsで行う必要があるのは、文字列を分割して属性を設定することだけです。

ただし、欠点もあります。

  1. 言葉や文字によるラッピングはありません(現時点ではtext-overflow: ''はFFでのみ機能します)
  2. 単語間で分割が発生する場合-最初の部分にスペースを入れてください。それ以外の場合は、折りたたまれます。
  3. direction: rtlのため、文字列の最後に感嘆符を付けることはできません-それらは文字列の左側に移動されます。 Wordの正しい部分をタグに入れ、感嘆符を::after疑似要素に入れることで、これを修正できると思います。しかし、私はまだそれを適切に機能させていません。

しかし、これらすべてが揃っているので、特にブラウザの境界線をドラッグするときは、jsfiddleページで簡単に実行できるので、とてもクールに見えます。 https://jsfiddle.net/extempl/93ymy3oL/ 。または、以下の最大幅を固定してスニペットを実行します。

スポイラーの下のGIF:

Gif

body {
  max-width: 400px;
}

span::before, span::after {
  display: inline-block;
  max-width: 50%;
  overflow: hidden;
  white-space: pre;
}

span::before {
  content: attr(data-content-start);
  text-overflow: Ellipsis;
}

span::after {
  content: attr(data-content-end);
  text-overflow: '';
  direction: rtl;
}
<span data-content-start="Look deep into nature, and then you " 
      data-content-end=  "will understand everything better"></span>

<br>
<span data-content-start="https://www.google.com.ua/images/branding/g" 
      data-content-end=  "ooglelogo/2x/googlelogo_color_272x92dp.png"></span>
20
extempl

そこで私の同僚は、余分なdom要素を使用しないソリューションを考え出しました。 divがオーバーフローするかどうかを確認し、最後のn文字のデータ属性を追加します。残りはCSSで行われます。

ここにいくつかのHTMLがあります:

<div class="box">
    <div class="Ellipsis" data-tail="some">This is my text it is awesome</div>
</div>
<div class="box">
    <div class="Ellipsis">This is my text</div>
</div>

そしてCSS:

.box {
    width: 200px;
}

.Ellipsis:before {
    float: right;
    content: attr(data-tail);
}

.Ellipsis {
    white-space: nowrap;
    text-overflow: Ellipsis;
    overflow: hidden;
}

これは必須のjsfiddleです: http://jsfiddle.net/r96vB/1/

9
Dan Perry

次のJavascript関数は、OS Xのように中間の切り捨てを行います。

function smartTrim(string, maxLength) {
    if (!string) return string;
    if (maxLength < 1) return string;
    if (string.length <= maxLength) return string;
    if (maxLength == 1) return string.substring(0,1) + '...';

    var midpoint = Math.ceil(string.length / 2);
    var toremove = string.length - maxLength;
    var lstrip = Math.ceil(toremove/2);
    var rstrip = toremove - lstrip;
    return string.substring(0, midpoint-lstrip) + '...' 
    + string.substring(midpoint+rstrip);
}       

途中の文字を省略記号に置き換えます。私の単体テストは示しています:

var s = '1234567890';
assertEquals(smartTrim(s, -1), '1234567890');
assertEquals(smartTrim(s, 0), '1234567890');
assertEquals(smartTrim(s, 1), '1...');
assertEquals(smartTrim(s, 2), '1...0');
assertEquals(smartTrim(s, 3), '1...90');
assertEquals(smartTrim(s, 4), '12...90');
assertEquals(smartTrim(s, 5), '12...890');
assertEquals(smartTrim(s, 6), '123...890');
assertEquals(smartTrim(s, 7), '123...7890');
assertEquals(smartTrim(s, 8), '1234...7890');
assertEquals(smartTrim(s, 9), '1234...67890');
assertEquals(smartTrim(s, 10), '1234567890');
assertEquals(smartTrim(s, 11), '1234567890');
6
johnvey

これはゲームの後半になるかもしれませんが、私はこれに対する解決策を見つけようとしていたところ、同僚が非常にエレガントな解決策を提案しました。 JSは必要ですが、多くは必要ありません。

ラベルを入れる必要があるサイズのdivがあるとします。

<div style="width: 200px; overflow: hidden"></div>

これで、ラベル付きの文字列とそれに適合するDOM要素(このdiv)の2つのパラメーターを取る関数ができました。

function setEllipsisLabel(div, label) 

まず、このラベルを使用してspanを作成し、それをdivに配置します。

var span = document.createElement('span');
span.appendChild(document.createTextNode(label));
span.style.textOverflow = 'Ellipsis';
span.style.display = 'inline-block';
div.appendChild(span);

text-overflowプロパティを "Ellipsis"に設定して、テキストが切り取られたときに、末尾にニース "..."を追加してこれを示します。また、displayを「インラインブロック」に設定して、これらの要素が後で操作できる実際のピクセル寸法を持つようにします。これまでのところ、純粋なCSSでは実現できなかったことは何もありません。

しかし、真ん中には省略記号が必要です。最初に、必要かどうかを確認する必要があります...これは、div.clientWidthspan.clientWidthと比較することで実行できます。spandivより広い場合にのみ省略記号が必要です。

省略記号が必要な場合は、まずWordの最後に固定数の文字を表示したいとします。たとえば、10とします。したがって、ラベルの最後の10文字のみを含むスパンを作成し、ラベルに貼り付けます。 div:

var endSpan = document.createElement('span');
endSpan.style.display = 'inline-block';
endspan.appendChild(document.createTextNode(label.substring(label.length - 10)));
div.appendChild(endSpan);

ここで、元のspanの幅をオーバーライドして、新しい幅に対応しましょう。

span.style.width = (div.clientWidth - endSpan.clientWidth) + 'px';

この結果、次のようなDOM構造ができました。

<div style="width: 200px; overflow: hidden">
   <span style="display: inline-block; text-overflow: Ellipsis; width: 100px">
      A really long label is shown in this span
   </span>
   <span style="display: inline-block"> this span</span>
</div>

最初のspantext-overflowが「省略記号」に設定されているため、最後に「...」が表示され、その後に2番目のスパンの10文字が表示されます。その結果、省略記号はdivのほぼ中央に表示されます。 。

EndSpanの10文字の長さをハードコードする必要もありません。これは、spanの初期幅とdivの初期幅の比率を計算し、ラベルの長さから適切な比率を引いて2で割ることによって概算できます。

3
levik

CSSではそれはできません。問題は、HTMLとCSSがさまざまなブラウザーやフォントで機能することになっており、一貫した方法で文字列の幅を計算することがほぼ不可能であることです。これは アイデア です。ただし、適切な幅の文字列が見つかるまで、何回か行う必要があります。

3
kgiannakakis

フレックスボックスに関するいくつかの調査の後、私はこの純粋なCSSソリューションを見つけました。

<div style="width:100%;border:1px solid green;display:inline-flex;flex-wrap:nowrap;">
   <div style="flex: 0 1 content;text-overflow: Ellipsis;overflow:hidden;white-space:nowrap;"> Her comes very very very very very very very very very very very very very very very very very very very long </div>
   <div style="flex: 1 0 content;white-space:nowrap;"> &nbsp;but flexible line</div>
</div>
2
Nikola Schou

このソリューションは、上記のソリューションを組み合わせたもので、最後のWord全体を短縮テキストの最後に配置します。ただし、最後のWordが利用可能なスペースの3分の1より長い場合は、左から短くされます。ダッシュ( "-")が見つかった場合はそこに切り取り、見つからない場合はとにかく切り取ります。

function truncate(text, textLimit) {
    if (!text) return text;
    if (textLimit < 1) return string;
    if (text.length < textLimit) return text;
    if (textLimit === 1) return text.substring(0,1) + '...';
    /* extract the last Word */
    var lastPart = text.slice( string.lastIndexOf(' ')+1 );
    /* if last Word is longer then a third of the max available space
       cut it from the left */
    var lastPartLimit = Math.ceil(textLimit / 3);
    if(lastPart.length > lastPartLimit) {
        var truncatedLastPart = lastPart;
        /* Try to find a dash and cut the last Word there */
        var lastDashPart = text.slice( text.lastIndexOf('-')+1 );
        if(lastDashPart.length < lastPartLimit){
            truncatedLastPart = lastDashPart;
        }
        /* If the last part is still to long or not available cut it anyway */
        if(truncatedLastPart.length > lastPartLimit) {
            var lastIndex = lastPart.length - lastPartLimit;
            truncatedLastPart = lastPart.substring( lastIndex );
        }
        lastPart = truncatedLastPart;
    }
    var dots = '... ';
    var firsPartLength = textLimit - lastPart.length - dots.length;
    return text.substring(0, firstPartLength) + dots + lastPart;
}

console.log( truncate("New York City", 10) ); // Ne... City (max of 10 characters)
console.log( truncate("New York Kindergarden", 14) ); // Ne...ergarden (max of 14 characters, last Word gets cut from the left by a third)
console.log( truncate("New York Kinder-garden", 14) ); // Ne...garden (max of 14 characters, last Word gets cut by the dash from the left)
1
flaskoln

これが私が見つけた最短のビットで、途中の3文字を...に置き換えます。

function shorten(s, max) {
  return s.length > max ? s.substring(0, (max / 2) - 1) + '...' + s.substring(s.length - (max / 2) + 2, s.length) : s
}
1

これにより、省略記号とプレースホルダーテキストの位置をもう少し制御できます。

function Ellipsis(str, maxLength, ellipsisLocationPercentage,placeholder) {
    /*
    ARGUMENTS:
    str - the string you want to maninpulate
    maxLength -  max number of characters allowed in return string
    ellipsisLocationPercentage (optional) - How far (percentage wise) into the return string you want the ellipses to be placed
        Examples:
        .85 : This is a very long string. This is a very long string. This is a very long string. This is a ver[...]very long string.
        .25 : This is a very long string. [...]g. This is a very long string. This is a very long string. This is a very long string.
    placeholder (optional) - this will be used to replace the removed substring. Suggestions : '...', '[..]', '[ ... ]', etc....
    */
    if(ellipsisLocationPercentage == null || isNaN(ellipsisLocationPercentage) || ellipsisLocationPercentage >= 1 || ellipsisLocationPercentage <= 0){
        //we've got null or bad data.. default to something fun, like 85% (that's fun, right??)
        ellipsisLocationPercentage = .85;
    }
    if(placeholder == null || placeholder ==""){
        placeholder = "[...]";
    }

    if (str.length > (maxLength-placeholder.length)) {
        //get the end of the string
        var beginning = str.substr(0, (maxLength - placeholder.length)*ellipsisLocationPercentage );
        var end = str.substr(str.length-(maxLength - placeholder.length) * (1-ellipsisLocationPercentage));
        return beginning + placeholder + end;
    }
    return str;
}

この関数を呼び出すには、次を呼び出します。

Ellipsis("This is a very long string. Be Scared!!!!", 8);//uses default values
Ellipsis("This is a very long string. Be Scared!!!!", 8,.5);//puts Ellipsis at half way point
Ellipsis("This is a very long string. Be Scared!!!!", 8,.75,'<..>');//puts Ellipsis at 75% of the way into the string and uses '<..>' as the placeholder
0
buddamus

きれいなカットを行い、短縮テキストの最後にWord全体を配置するために、以下の関数を使用しました。

function prepareText(text){
  var returnString = text;
  var textLimit = 35;
  if(text.length > textLimit){
    var lastWord = text.slice( text.lastIndexOf(' ')+1 );
    var indexFromEnd = lastWord.length;
    var Ellipsis = '... ';

    returnString = text.slice(0, textLimit - indexFromEnd - Ellipsis.length);
    returnString = returnString + Ellipsis + lastWord;
  }
  return returnString;
}

$('#ex1Modified').html( prepareText( $('#ex1').html() ) );

$('#ex2Modified').html( prepareText( $('#ex2').html() ) );

$('#ex3Modified').html( prepareText( $('#ex3').html() ) );
body{color:#777; font-family: sans-serif;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>Shortened Quotes from Albert Einstein</h2>

<div id="ex1">"The true sign of intelligence is not knowledge but imagination."</div>
<div id="ex1Modified"></div>
<br>
<div id="ex2">"Look deep into nature, and then you will understand everything better."</div>
<div id="ex2Modified"></div>
<br>
<div id="ex3">"You can't blame gravity for falling in love."</div>
<div id="ex3Modified"></div>
0
aero

別の刺し傷:

function truncate( str, max, sep ) {
    max = max || 10;
    var len = str.length;
    if(len > max){
        sep = sep || "...";
        var seplen = sep.length;
        if(seplen > max) { return str.substr(len - max) }

        var n = -0.5 * (max - len - seplen);
        var center = len/2;
        return str.substr(0, center - n) + sep + str.substr(len - center + n);
    }
    return str;
}

console.log( truncate("123456789abcde") ); // 123...bcde (using built-in defaults) 
console.log( truncate("123456789abcde", 8) ); // 12...cde (max of 8 characters) 
console.log( truncate("123456789abcde", 12, "_") ); // 12345_9abcde (customize the separator) 
0
bob

ここにエレガントなソリューションがあります:

function truncateMiddle(Word) {
    const tooLongChars = 15; // arbitrary

    if (Word.length < tooLongChars) {
        return Word;
    }

    const Ellipsis = '...';
    const charsOnEitherSide = Math.floor(tooLongChars / 2) - Ellipsis.length;

    return Word.slice(0, charsOnEitherSide) + Ellipsis + Word.slice(-charsOnEitherSide);
}
0
Jeremy Moritz

途中、nearEnd、Endでトリミングできる関数を作成しましたが、サーバー側で最終的に必要だったため、まだテストされていません

//position acceptable values : middle, end, closeEnd
function AddElipsis(input, maxChars, position) {
    if (typeof input === 'undefined') {
        return "";
    }
    else if (input.length <= maxChars) {
        return input;
    }
    else {
        if (position == 'middle') {
            var midPos = Math.floor(maxChars / 2) - 2;
            return input.substr(0, midPos) + '...' + input.substr(input.length - midPos, input.length);
        }
        else if (position == 'closeEnd') {
            var firstPart = Math.floor(maxChars * 0.80) - 2;
            var endPart = Math.floor(maxChars * 0.20) - 2;
            return input.substr(0, firstPart) + '...' + input.substr(input.length - endPart, input.length);
        }
        else {
            return input.substr(0, maxChars - 3) + '...';
        }
    }
}
0
Menelaos Vergis