JavaScriptで表示文字数の制限

### この記事の目的
個人的にブログサイトを作っていて文字数の表示制限がしたいと思い調べたところ意外と簡単に実装できたのでアウトプットも兼ねて記事を書こうと思います。


### イメージはこんな感じ
<img width="825" alt="スクリーンショット 2020-06-14 13.43.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535379/5dbb102f-1747-daec-7ffb-97fb5fff8064.png">

文字が多い場合は末尾が...になっていますね。

### 準備

index.html
omitted.js(省略という意味の英語)
ファイル名は自分のわかりやすいように変えてもらって構いません。
ロジックだけを説明したいので最小限のファイル構成にしています。

##### エディタ
筆者はVScodeを使います。お好きなエディタをお使いください。

### index.htmlの作成

<img width="1680" alt="スクリーンショット 2020-06-14 13.53.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535379/c9f07228-c189-cda4-8a34-4263c3bc9e9a.png">

お好きなディレクトリを作ってその直下にindex.htmlを作ってください。筆者はディレクトリ名をomittedにしました。

HTMLを書いていきます。
ちなみにVScodeの機能で!を押してからタブを押すと大枠を作成してくれます。
!で変換したらここまで書いてください。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>文字数制限の実装</title>
</head>
<body>
  <script src="js/omitted.js"></script>
</body>
</html>
```

### omitted.jsの作成

ここまでできたらomitted.jsを作成します。
VScodeの機能で⌘+JSへのリンクをクリックするとファイルを作成してくれるのでこれで作成すると便利です。

以下のような表示が出ますが、ファイルの作成をクリックしてください。

<img width="1680" alt="スクリーンショット 2020-06-14 14.02.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535379/322949d0-0305-4ce2-f2b0-d86dcc825e89.png">

ここまでできたらHTMLに記述を追加していきます。
できるだけシンプルにするためにli要素を2つだけ用意しました。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>文字数制限の実装</title>
</head>
<body>
<!-- ここから -->
  <ul>
    <li>テストの文章1です</li>
    <li>テストの文章2ですテストの文章2です</li>
  </ul>
<!-- ここまで追加 -->
  <script src="js/omitted.js"></script>
</body>
</html>
```

それではブラウザで確認しましょう。

<img width="370" alt="スクリーンショット 2020-06-14 15.01.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535379/f5e48c2f-6ea0-50f9-c233-defc78145471.png">

なんてことはないですね。今回はJSでの表示文字数の制限にフォーカスしているのでスタイルは整えません。

ここまでできたらいよいよ本題のJSを書いていきます。

### JSの実装

まず初めにli要素を取得してその要素をforEach文で一つずつ取得します。

```javascript:omitted.js
// document.querySelectorAllでli要素を全て取得する。
let contents = document.querySelectorAll('li');
// liは2つあるのでcontentsという変数に格納しました。

// contentsをforEachで一つずつ取得、引数が一つの場合は()を省略できる。(content) => {}の()を省略している。
contents.forEach(content => {
  content.textContent = omittedContent(content.textContent);
  // content.textContentで文字列を取得できる（loop1回目の場合は"テストの文章1です"が入っている)
  // 関数omittedContentに引数としてcontent.textContentを渡しておく。
});

```

1回目のloopではcontent.textContentで "テストの文章1です。" が取得できる。
その値を変更してあげれば良いのでomittedContent()という関数を作成しそれを代入することによって表示文字数の制限を行います。
また引数にはli要素の中身の文字列を入れ関数に渡してあげます。

(注)現時点では関数の宣言がされていないというエラーが起こると思います。このあと関数を宣言するので、今はエラーは気にせず先に進めてください


それでは関数を作っていきます。

```javascript:omitted.js
//　以下に追加

// 引数でcontent.textContentを受け取る。
function omittedContent(string) {
  // 定数で宣言
  const MAX_LENGTH = 10;

  // もしstringの文字数がMAX_LENGTH（今回は10）より大きかったら末尾に...を付け足して返す。
  if (string.length > MAX_LENGTH) {

    // substr(何文字目からスタートするか, 最大値);
    return string.substr(0, MAX_LENGTH) + '...';
  }
  //　文字数がオーバーしていなければそのまま返す
  return string;
}
```
substrを使い文字数を制限して文字数がオーバーした場合末尾に...を追加しています。
文字数がオーバーしなければそのままの文字列を返しています。

### 結果
<img width="299" alt="スクリーンショット 2020-06-14 15.00.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535379/7b6564ae-128b-b1a1-549e-4bce6d41126b.png">

文字数を10に制限しているので2つ目のli要素の文字列が省略されているのがわかります。

### JavaScriptのコード(完成版)

```javascript:omitted.js
// document.querySelectorAllでli要素を全て取得する。
let contents = document.querySelectorAll('li');
// liは2つあるのでcontentsという変数に格納しました。

// contentsをforEachで一つずつ取得、引数が一つの場合は()を省略できる。(content) => {}の()を省略している。
contents.forEach(content => {
  content.textContent = omittedContent(content.textContent);
  // content.textContentで文字列を取得できる（loop1回目の場合は"テストの文章1です"が入っている)
});

// 引数でcontent.textContentをstringという変数名で受け取る。
function omittedContent(string) {
  // 定数で宣言
  const MAX_LENGTH = 10;

  // もしstringの文字数がMAX_LENGTH（今回は10）より大きかったら末尾に...を付け足して返す。
  if (string.length > MAX_LENGTH) {

    // substr(何文字目からスタートするか, 最大値);
    return string.substr(0, MAX_LENGTH) + '...';
  }
  //　文字数がオーバーしていなければそのまま返す
  return string;
}

```

### 最後に
なるべくシンプルに作ってみました。
アプリに組み込む際は文章などは動的なデータになると思うのでwindow.onload等でページを読み込んでから使うなどしてみてください。