lightbox2の使い方とカスタマイズについて（メモ）

#この投稿について
作業進捗の備忘録、学習効果の向上を目的として記録していきます。
学習しながら作業を進めておりますので、情報が間違っている場合も多々あると思います。
正しい情報は公式ドキュメントを参考にしてください。

#開発環境
* macOS High Sierra 10.13.6
* Anaconda 3
* Python 3.7.7
* Djnago 3.0.6
* VisualStudioCode

※記事内のHTMLコードやフォルダ構成についてはアプリ開発途中のものを使用していますので、あらかじめご了承ください。

#lightbox2とは

公式サイト
https://lokeshdhakar.com/projects/lightbox2/

Webサイト上でいい感じに写真を閲覧できるようにするためのJavaScriptライブラリです。

#lightbox2でやりたいこと
ページをめくる感じに写真を次々閲覧したい。
なんかいい感じに写真を見せたい。

#導入してみる
`lightbox.js`を公式のGithub（https://github.com/lokesh/lightbox2/releases）からダウンロードし、それぞれアプリ内のstaticフォルダ内に設置します。
今回は少しカスタマイズして使用したいので、jsはminファイルではなく、オリジナルのものを使いました。


```
app/static/js/lightbox.js
```
lightbox.cssはダウンロードせずに、<head>内で読み込んで使用することにしました。

#HTMLの記述
head内にそれぞれ必要なファイルを読み込むための記述をします。jQueryも使うみたいなのでついでに読み込みます。

```html:base.html
<head>
......
<link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="{% static 'js/lightbox.js' %}"></script>
</head>
```

次に、写真を表示するページです。


```html:index.html
{% extends 'base.html' %}

{% block bodyblock %}
<div class="row pb-5">
    {% for pic in obj %}
    <div class="col-md-3 mt-5">
        <a href="{{ pic.picture.url }}" data-lightbox="group"> 
            <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250">
        </a>
    </div>
    {% endfor %}
</div>
{% endblock %}

```
写真DBからクエリセットを取得してobjに読み込んでいます。
for文でサムネイルを並べるよう記述しています。

imgタグを内包しているaタグに`data-lightbox="group"`の属性をつけることで、ページめくりの対象となる画像であることが認識されます。

#動作確認
写真のサムネイルを並べているページにアクセスし、写真をクリックすると、ポップアップウインドウが表示され、写真の左右にある矢印をクリックすると、隣の画像が表示されます。
（公式サイトサンプルのような動作が確認できると思います。）

#カスタマイズしてみる
画像を表示させるだけだと少し物足りなく感じたので、写真情報編集用のボタン（公開非公開、編集、削除など）を表示させることを試みました。
情報を探していると、写真が表示されるウインドウにキャプションを入れられるようで、方法は、先ほど`data-lightbox="group"`の属性を追加したタグに、`data-title="キャプションしたい文字列"`の属性と属性値を追加すれば良いとのこと。

以下のようにhtmlを編集すれば、タイトルのキャプションをつけるのは簡単そうです。※モデルにtitleフィールドがある場合。

```html:index.html
{% extends 'base.html' %}

{% block bodyblock %}
<div class="row pb-5">
    {% for pic in obj %}
    <div class="col-md-3 mt-5">
        <a href="{{ pic.picture.url }}" data-lightbox="group" data-title="{{ pic.title }}"> 
            <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250">
        </a>
    </div>
    {% endfor %}
</div>
{% endblock %}

```

今回は編集用のボタンをキャプション部分に表示してみます。

#lightbox.jsを編集してみる
```javascript:lightbox.js(114行目)
    // Github issue: https://github.com/lokesh/lightbox2/issues/663
    $('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" aria-label="Previous image" href="" ></a><a class="lb-next" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));

```
ここで、画像を表示するポップアップウインドウのHTMLを発行しているようです。このあたりを編集することでレイアウト等をカスタマイズできそうです。

```html:編集後
・・・・・<span class="lb-caption"></span><div class="lightbox-buttons"><a class="update" href="#"></a></div><span class="lb-number"></span>・・・・・

```
既存のタグは改変したくなかったので、captionを表示するためのタグの後ろに、ボタンを格納するための`<div class="lightbox-buttons"><a class="update btn btn-primary" href="#">Update</a></div>`を追記しました。

次に、index.htmlを以下のように編集します。

```html:index.html
{% extends 'base.html' %}

{% block bodyblock %}
<div class="row pb-5">
    {% for pic in obj %}
    <div class="col-md-3 mt-5">
        <a href="{{ pic.picture.url }}" data-lightbox="group" update_url="{% url 'update' %}"> 
            <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250">
        </a>
    </div>
    {% endfor %}
</div>
{% endblock %}

```


```javascript:lightbox.js(220~226行目)
    function addToAlbum($link) {
      self.album.push({
        alt: $link.attr('data-alt'),
        link: $link.attr('href'),
        title: $link.attr('data-title') || $link.attr('title')
      });
    }
```

この辺りのコードで、index.htmlのaタグ内に記載したdata-title属性の属性値を取得しているようです。

なので、以下のように編集します。

```javascript:編集後
    function addToAlbum($link) {
      self.album.push({
        alt: $link.attr('data-alt'),
        link: $link.attr('href'),
        update: $link.attr('update_url'),
      });
    }
```
これにより、index.htmlのupdare_urlの属性値(`{% url 'update' %}`)が読み取られ、albumのupdateに格納されます。

```javascript:lightbox.js(468~483行目)
// Display caption, image number, and closing button.
  Lightbox.prototype.updateDetails = function() {
    var self = this;

    // Enable anchor clicks in the injected caption html.
    // Thanks Nate Wright for the fix. @https://github.com/NateWr
    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
      this.album[this.currentImageIndex].title !== '') {
      var $caption = this.$lightbox.find('.lb-caption');
      if (this.options.sanitizeTitle) {
        $caption.text(this.album[this.currentImageIndex].title);
      } else {
        $caption.html(this.album[this.currentImageIndex].title);
      }
      $caption.fadeIn('fast');
    }
```
このコードで、220~226行で作成したalbumのtitleと紐づいている値の存在を確認して、データがあるようであれば114行目で生成した`<span class="lb-caption"></span>`にHTMLなりテキストなりを入力する処理をしています。

なので、以下のように編集します。

```javascript:468~483行目
// Display caption, image number, and closing button.
  Lightbox.prototype.updateDetails = function() {
    var self = this;

    // Enable anchor clicks in the injected caption html.
    // Thanks Nate Wright for the fix. @https://github.com/NateWr
    //update url injection.
    if (typeof this.album[this.currentImageIndex].update !== 'undefined' &&
      this.album[this.currentImageIndex].update !== '') {
      var $caption = this.$lightbox.find('.update');
      $caption.attr('href',this.album[this.currentImageIndex].update);
      $caption.fadeIn('fast');
    }
```
これにより、albumのupdateと紐づいている値の存在を確認して、データがあるようであれば114行目で生成した`<a class="update" href="#"></a>'のhref値を指定したurlに書き換えることができます。
これでlightboxのキャプション部分にリンクを設定することができました。

###その他
```javascript:285行目
this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
```
上記に独自に追加した属性を追記しないと、意図しないところでボタンが表示されたままになってしまったりするので、記載しておいた方が良い。

```javascript:編集後
this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption, .update').hide();