1. ホーム
  2. ジャバスクリプト

[解決済み】長い文字列をスマートに切り捨てる方法

2022-04-06 07:14:13

質問

JavaScriptで文字列を切り捨て、最後に省略記号を付けるための、より洗練されたソリューション/ライブラリはありますか?

if (string.length > 25) {
  string = string.substring(0, 24) + "...";
}

解決方法は?

基本的には、与えられた文字列の長さをチェックします。もし、与えられた長さより長ければ n 長さに切り詰める n ( substr または slice を追加し、HTMLエンティティ … (...) を切り取った文字列に追加します。

このようなメソッドは次のようになります。

function truncate(str, n){
  return (str.length > n) ? str.substr(0, n-1) + '…' : str;
};

もし、「より洗練された」というのが、文字列の最後の単語の境界で切り捨てるという意味であれば、追加のチェックが必要です。 まず、文字列を目的の長さに切り詰め、次にその結果を最後の単語の境界で切り詰めます。

function truncate( str, n, useWordBoundary ){
  if (str.length <= n) { return str; }
  const subString = str.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

を拡張することができます。 String プロトタイプに関数を追加します。その場合 str パラメータを削除し str に置き換える必要があります。 this :

String.prototype.truncate = String.prototype.truncate || 
function ( n, useWordBoundary ){
  if (this.length <= n) { return this; }
  const subString = this.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

より独断的な開発者は、そのことを強く叱るかもしれません(" 所有していないオブジェクトを修正してはいけない "。私は気にしませんが)。

を拡張しないアプローチ。 String プロトタイプを作成することです。 独自のヘルパーオブジェクトを作成し、そこに指定された(長い)文字列を格納します。 と、それを切り捨てる前述のメソッドです。これが、このスニペット は、以下のようになります。

const LongstringHelper = str => {
  const sliceBoundary = str => str.substr(0, str.lastIndexOf(" "));
  const truncate = (n, useWordBoundary) => 
        str.length <= n ? str : `${ useWordBoundary 
          ? sliceBoundary(str.slice(0, n - 1))
          : str.substr(0, n - 1)}&hellip;`;
  return { full: str,  truncate };
}; 
const longStr = LongstringHelper(`Lorem ipsum dolor sit amet, consectetur 
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore 
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute 
irure dolor in reprehenderit in voluptate velit esse cillum dolore 
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 
proident, sunt in culpa qui officia deserunt mollit anim id est laborum`);

const plain = document.querySelector("#resultTruncatedPlain");
const lastWord = document.querySelector("#resultTruncatedBoundary");
plain.innerHTML = 
  longStr.truncate(+plain.dataset.truncateat, !!+plain.dataset.onword);
lastWord.innerHTML = 
  longStr.truncate(+lastWord.dataset.truncateat, !!+lastWord.dataset.onword);
document.querySelector("#resultFull").innerHTML = longStr.full;
body {
  font: normal 12px/15px verdana, arial;
}

p {
  width: 450px;
}

#resultTruncatedPlain:before {
  content: 'Truncated (plain) n='attr(data-truncateat)': ';
  color: green;
}

#resultTruncatedBoundary:before {
  content: 'Truncated (last whole word) n='attr(data-truncateat)': ';
  color: green;
}

#resultFull:before {
  content: 'Full: ';
  color: green;
}
<p id="resultTruncatedPlain" data-truncateat="120" data-onword="0"></p>
<p id="resultTruncatedBoundary" data-truncateat="120" data-onword="1"></p>
<p id="resultFull"></p>

最後に、HTMLノード内の長い文字列を切り詰めるためにのみcssを使用することができます。これはあまり制御できませんが、実行可能な解決策になるかもしれません。

body {
  font: normal 12px/15px verdana, arial;
  margin: 2rem;
}

.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 30vw;
}

.truncate:before{
  content: attr(data-longstring);
}

.truncate:hover::before {
  content: attr(data-longstring);
  width: auto;
  height: auto;
  overflow: initial;
  text-overflow: initial;
  white-space: initial;
  background-color: white;
  display: inline-block;
}
<div class="truncate" data-longstring="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."></div>