脱jQuery!文字量によって表示を制限するJavaScript

こんにちは、ナカムラです。
今回は文字数などのコンテンツ量によって表示を制限するJavaScriptを解説していきます。
jQueryを使わないネイティブでの書き方になります。
※IEにも対応したい場合は注意点があります。詳しくは解説の中で記載しています。

作りたいもの

要素の高さが40pxを超える場合、一部を隠し、「open」ボタンをクリックすると全て表示する。
「close」ボタンを押すと隠した状態に戻る。

DEMO

See the Pen textLimit by Nakamura (@takayo-nakamura) on CodePen.

解説

では細かく見ていきます。

JavaScriptを適用したい要素

  const elements = document.querySelectorAll('.js-textLimit');
  elements.forEach(e => {
    // 要素に適用する処理を書きます
  });

classに「js-textLimit」が付与されている要素(以下、適用したい要素と呼びます)に対して処理を当てていきます。
※ページ内に複数存在することが多いと思いますのでforEachを使うことで全ての適用したい要素に当てます。

各メソッドについて詳しくはこちらをご覧ください。
querySelectorAll:Document.querySelectorAll() - Web API | MDN
forEach:Array.prototype.forEach() - JavaScript | MDN

要素の判定

  const textHeight = e.clientHeight;
   if (textHeight > 40) {
    // 40pxより大きかった時の処理を書きます
   }

適用したい要素の高さを取得し、if文で40px以上かどうかを判定します。
※今回は大きかった場合にのみ行う処理なのでelseの処理はありません。

ステータスの変更

e.classList.add('is-hide','-long');

適用したい要素に対してclassを追加します。
JavaScriptでclassを付け替え、スタイルシートで表示を制御します。
※IEの場合、複数を同時にaddすることができません。別々に付与するか配列にして当てる必要がありますのでご注意ください。

「is-hide」は隠したい時のクラスです。
heightとoverflowプロパティで隠します。

「-long」は全て表示した時のボタンの位置を調整するために当てたスタイルなので、デザインによっては不要です。

.classListは要素のclass属性値を指します。
.removeで外し、.addで付与します。

ボタンの追加(要素を追加する)

    let newNode = document.createElement('button');
    newNode.setAttribute('type', 'button');
    const newContent = document.createTextNode('open');
    newNode.appendChild(newContent);
    e.insertBefore(newNode, null);

表示はclassを当てることによってスタイルで制御しますが、開閉する動作にはボタンが必要になります。
JavaScriptでボタンを追加していきましょう。
どんな処理を行っているかは下記の通りです。

let newNode = document.createElement('button');
button要素を生成する

newNode.setAttribute('type', 'button');
生成した要素のtype属性をbuttonにする

const newContent = document.createTextNode('open');
生成した要素に入れたい文字列'open'を生成する

newNode.appendChild(newContent);
生成した要素に生成した文字列を追加する

e.insertBefore(newNode, null);
生成した要素を適用したい要素に追加する

各メソッドについて詳しくはこちらをご覧ください。
createElement:Document.createElement() - Web API | MDN
setAttribute:element.setAttribute - Web API | MDN
createTextNode:Document.createTextNode() - Web API | MDN
appendChild:Node.appendChild - Web API | MDN
insertBefore:Node.insertBefore() - Web API | MDN

クリックの動作

    const btn = e.querySelector('button');
    btn.addEventListener('click', () => {
      const status = e.classList.contains('is-hide');
      if (status) {
        // 開く
        e.classList.remove('is-hide');
        btn.innerHTML = 'close';
      } else {
        // 閉じる
        e.classList.add('is-hide');
        btn.innerHTML = 'open';
      }
    });

追加したボタンをクリックした時の処理です。
addEventListenerで「クリックした時」のイベントを書いていきます。
適用したい要素のステータスがどの状態かを判定し、classとボタンの文字列を変更します。
ステータスはclassにis-hideが存在するかどうかで開いているか、閉じているかがわかります。

.innerHTMLはbtn(button要素)の内容を指します。
.innerHTMLに新たに文字列を挿入することで文字列を差し替えます。

各メソッドについて詳しくはこちらをご覧ください。
addEventListener:EventTarget.addEventListener() - Web API | MDN
innerHTML:element.innerHTML - Web API | MDN

最後に

今回は高さを判定する仕様にしましたが、文字数でも判定できます。
その場合はこちら

  const txt = e.textContent.length;
  if(txt > 50){
  }

.textContentで適用したい要素の文字列を取得し、
.lengthで文字数を取得します。

各メソッドについて詳しくはこちらをご覧ください。
textContent:Node.textContent - Web API | MDN
length:Array.length - JavaScript | MDN

この他にも作りたい仕様に合わせてカスタマイズしてみてください。