プログラマ・アゲイン blog

還暦を過ぎたけどプログラマ復帰を目指してブログ始めました

ソースコードを貼り付けるボックスを非表示にする

ソースコード貼り付け用ボックスの表示について

前回の「ソースコードを貼り付けるボックスを作成 (3)」で、ソースコードを張り付けるボックスの作成ができました。しかし、今までに書いたウェブのページを見てみると、ソースコードを張り付けたために長くなっており、読んでいくためにはスクロールをたくさんしなくてはいけません。

そこで、初期はソースコードのブロックを非表示にしておき、「表示」ボタンを押すことにより表示されるようにしたいと思います。今までのJavaScriptCSSを基に、ソースコード・ブロックの表示/非表示を作成しました。

 

表示/非表示のイメージ

どのような状態のものを、どのようにしたいか、についてですが、目次の表示/非表示と同様に以下のようなイメージです。ちなみに、中身のJavaScriptは、作成・テスト中のものです。

<!-- //クリックすると表示されるボックス -->
<script>
  $(function(){
    let $Contents = $(".source")
    $($Contents).before('<span style="font-size: 150%; color: #333;">ソースを表示する</span><p class="show-area">[表示]</p>');
    $(".show-area").click(function(){
      var $this = $(this);
      if($Contents.css('display') == 'none'){
        $Contents.slideDown(400),
        $this.text("[隠す]");
      }else{
        $Contents.slideUp(400),
        $this.text("[表示]")
      };
    });
  });
</script>

 

開発においての考慮点

ソースコード貼り付け用ボックスの表示/非表示の機能作成において、以下の点を考慮しました。

目次との違い

目次は、Webページでは1回しか出現しません。しかし、ソースコードのブロックは複数回出現します。単純に目次の表示/非表示を基に作成すると、一つのブロックの「表示」ボタンのクリックで、すべてのブロックが表示されてしまいます。

したがって、どのブロックの「表示」ボタンがクリックされたのか、を意識する必要があり、その機能の追加が必要です。

開発の言語

開発にあたっての言語ですが、ソースコード貼り付け用ボックスはネイティブなJavaScriptで作成しています。しかし、目次の表示/非表示は、jQueryライブラリを使用して作成しています。

目次の表示/非表示をベースに開発しようと思いますので、jQueryライブラリを調べて使用することにします。jQueryを調べるにあたって、以下のページを参考にしました。

www.jquerystudy.info

今までのブログ

今までのブログの中で使用してきたソースコード貼り付け用ボックスについても、表示/非表示されるようにするか、も考えました。

ブログを書いた時の状態を残しておきたいので、過去のソースコード貼り付け用ボックスには影響しないように、新規で開発したJavaScriptCSSを追加する形で作成します。

 

開発したソースと内容

実際に開発(というか、変更)した内容について、記述します。

 

目次の表示/非表示

目次の表示/非表示は、他の方が開発したJavaScriptCSSをコピー&ペーストして使用させていただいていました。元々のソースは、以下のものです。

目次の表示/非表示のJavaScript
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
  $(function(){
    var $Contents = $(".table-of-contents")
    $($Contents).before('<span style="font-size: 150%; color: #333;">目次</span><p class="show-area">[表示]</p>');
    $(".show-area").click(function(){
      var $this = $(this);
      if($Contents.css('display') == 'none'){
        $Contents.slideDown(400),
        $this.text("[隠す]");
      }else{
        $Contents.slideUp(400),
        $this.text("[表示]")
      };
    });
  });
</script>
目次の表示/非表示のCSS
.table-of-contents{
  display: none;
}
.show-area{
  display: inline-block;
  padding: 10px;
  border-radius: 5px;
  cursor: pointer;
  margin-bottom: 0;
  color: blue;
}

 

変更した内容

以下のポイントで、前述のJavaScriptCSSを変更して作成しました。また、それらを使用するために、HTMLでの記述も変更しました。

ソースコード・ボックスの選択

クリックされた[表示]ボタンの次のpreタグ要素である、該当ソースコード貼り付け用ボックスのjQueryオブジェクトを、jQueryの.next()メソッドで取得しています。

取得したjQueryオブジェクトを変数$sourceに代入し、そのCSSルールのdisplayプロパティの値によりslideDownメソッドで「非表示」→「表示」、slideUpメソッドで「表示」→「非表示」を切り替えています。

<script>
  $(function(){
    const $Contents = $(".source-block")
    ・・・
      let $source = $(this).next("pre");
      if($source.css("display") == "none") {
        $source.slideDown(400),
        $(this).text("[隠す]");
      }else{
        $source.slideUp(400),
        $(this).text("[表示]");
      }
    ・・・
  });
</script>
クラス名

既存の目次やソースコード貼り付け用ボックスと区別するため、以下のようにクラス名を付けました。

  • ソースコード貼り付け用ボックスのクラス名 → source-block
  • [表示]ボタンのクラス名 → show-source

以下の、赤字の部分を変更しましたものを作成しました。

HTML

<pre class="source-block lang-HTML" data-lang="HTML"><code class=source-code>
・・・
</code></pre>

JavaScript

<script>
  $(function(){
    const $Contents = $(".source-block")
    $Contents.before('<span style="font-size: 100%; color: #333;"> ソースを表示する</span><p class="show-source">[表示]</p>');
    $(".show-source").click(function() {
      ・・・
    });
  });
</script>

CSS

.show-source{
  ・・・
}
pre.source-block {
  ・・・
}
pre.source-block::before {
  ・・・
}
初期は非表示の設定

ページが表示された時にソースコードのボックスを非表示にするために、displayプロパティにnoneを追加します。

これで、最初のページをロードした時点では、ソースコード貼り付け用ボックスの要素が表示されなくなります。

pre.source-block {
  ・・・
  display: none;
  ・・・
}
クラス名変更への追加対応

ソースコード貼り付け用ボックスのクラス名を「source-block」に変更したため、ソースコードの行にdivタグを付けるJavaScriptも作成する必要があります。

その際、クラス名を変更するだけでなく、変数宣言している変数名も変更します。残っている、今までのJavaScriptで宣言している変数名とカブってしまうためです。なお、Functionの中は変数のスコープが違うので変数名がダブってもいいと思うのですが、名前の統一感を持たせるために同時に変更しました。

<script type="text/javascript">
  const sourceBlocks = document.getElementsByClassName('source-block');
  [].forEach.call(sourceBlocks, function(sourceBlock) {
    if (!/lang/.test(sourceBlock.className)) {
      return;
    }
    const sourceLines = sourceBlock.innerHTML.split(/\n/);
    ・・・
    sourceBlock.innerHTML = sourceLine;
  });
</script>
その他の変更

JavaScriptを変更する際に、varで変数宣言していたところは、let または constを使用するようにしました。

また、jQueryオブジェクトとDOM要素を意識して、メソッドが操作する対象のjQueryオブジェクトの書き方を変更しました。

<script>
  $(function(){
    const $Contents = $(".source-block")
    $Contents.before('<span style="font-size: 100%; color: #333;"> ソースを表示する</span><p class="show-source">[表示]</p>');
    $(".show-source").click(function() {
      let $source = $(this).next("pre");
      if($source.css("display") == "none") {
        $source.slideDown(400),
        $(this).text("[隠す]");
      }else{
        $source.slideUp(400),
        $(this).text("[表示]");
      }
    });
  });
</script>

 

開発したソースコード

結果として、開発したJavaScriptCSSは、以下のようになりました。

HTML
<pre class="source-block lang-HTML" data-lang="JavaScript"><code class=source-code>
・・・
</code></pre>
JavaScript
<script>
  $(function(){
    const $Contents = $(".source-block")
    $Contents.before('<span style="font-size: 100%; color: #333;"> ソースを表示する</span><p class="show-source">[表示]</p>');
    $(".show-source").click(function() {
      let $source = $(this).next("pre");
      if($source.css("display") == "none") {
        $source.slideDown(400),
        $(this).text("[隠す]");
      }else{
        $source.slideUp(400),
        $(this).text("[表示]");
      }
    });
  });
</script>
<script type="text/javascript">
  const sourceBlocks = document.getElementsByClassName('source-block');
  [].forEach.call(sourceBlocks, function(sourceBlock) {
    if (!/lang/.test(sourceBlock.className)) {
      return;
    }
    const sourceLines = sourceBlock.innerHTML.split(/\n/);
    let sourceLine = "";
    sourceLines.forEach(function(line) {
      if(line !== "") {
        sourceLine += '<div class="source-line">' + line + '</div>';
      }
    });
    sourceBlock.innerHTML = sourceLine;
  });
</script>
CSS
.show-source{
  border-radius: 5px;
  color: blue;
  cursor: pointer;
  display: inline-block;
  margin-bottom: 0;
  padding: 10px;
}
pre.source-block {
  background-color: #f8f8f8;
  border:2px solid #ccc; /*追加:コード表示部分の枠設定*/
  display: none;
  font-size: 14px;
  line-height: 16px;
  overflow: auto;
  padding: 20px;
  padding-top: 30px;
  position:relative; /*追加*/
}
pre.source-block::before {
  background: #eee;
  border: 3px outset #eceef1;
  border-radius: 10px; 
  color: #333;
  content: attr(data-lang);
  display: inline-block;
  font-size: 12px;
  font-weight: bold;
  line-height: 12px;
  margin-left: -10px;
  margin-top: -30px;
  padding: 4px 10px 4px;
  position: absolute;
}

 

これで、ソースコード貼り付け用ボックス関連の開発は一段落しました。