属性を与えるだけで画像をモーダル化できるコード【コピペ】

# 概要
imgタグに属性を添えるだけで、画像をモーダル表示できるコードを作成した。

## 仕様
 イベントが発生して初めてDOM生成する。そのせいでちょっと重い。


#使い方
モーダル化させたいimgタグに

属性　`modal-image="hoge.jpeg"`

を追加する。

```html:例
<img src="thumbnail.jpeg" modal-image="original.jpeg">
```

##値
modal-image=" `モーダル時に表示させたい画像のパス`"
表示している画像(サムネ画像)とモーダル時の画像が同じであれば値は**空**でOK。




#コピペコード

あとは下記コードをはりつける。

```js:JavaScript
/**モーダルのDOM生成 */
const img_modal = document.querySelectorAll('[modal-image]');
/*activeクラスを付与*/
img_modal.forEach(function(index) {
  index.addEventListener('click', openModal);
});

/**
 * DOM生成の後、activeクラスを追加
 */
function openModal() {
  this.parentElement.appendChild(makeModal(this));
  window.setTimeout(() => {
    this.parentElement.getElementsByClassName('gm-modal')[0].classList.add('active');
  }, 10);
  const el_modal = document.querySelectorAll('.js_close');
  el_modal.forEach(function(index) {
    index.addEventListener('click', closeModal);
  });
}

/**
 * activeクラスの削除の後、DOM削除
 */
function closeModal() {
  let gmModal = document.getElementsByClassName('gm-modal')[0];
  gmModal.classList.remove('active');
  window.setTimeout(() => {
    gmModal.parentNode.removeChild(gmModal);
  }, 500);
}

/**
 * モダールのDOMを生成する
 * @param el_img modal-image属性をもった要素
 */
function makeModal(el_img) {
  let DOM = {
    modal : document.createElement('article'),
    overlay : document.createElement('div'),
    content : document.createElement('div'),
    close : document.createElement('button'),
    divImg : document.createElement('div'),
    img : document.createElement('img'),
  }
  const cl_name = 'gm-modal';
  //.modal
  DOM.modal.classList.add(cl_name);
  //&__overlay
  DOM.overlay.classList.add(cl_name + '__overlay', 'js_close');
  //&__content
  DOM.content.classList.add(cl_name + '__content');
  DOM.divImg .classList.add(cl_name + '__img');
  DOM.close.setAttribute('aria-label', 'Close modal');
  DOM.close.classList.add(cl_name + '__close', 'js_close');
  DOM.close.innerHTML = '&times;';
  //altに値があるなら引き継ぐ
  const altValue = el_img.getAttribute('alt');
  if (altValue!='') {
    DOM.img.alt = altValue;
  }
  let modalImage = el_img.getAttribute('modal-image');
  //属性値が空ならsrcと同じ画像を表示
  DOM.img.setAttribute('src', (modalImage=='')? el_img.getAttribute('src') : modalImage);
  DOM.divImg.appendChild(DOM.img);
  DOM.content.appendChild(DOM.close);
  DOM.content.appendChild(DOM.divImg);
  DOM.modal.append(DOM.overlay);
  DOM.modal.append(DOM.content);

  return DOM.modal;
}
```

```css:CSS
img[modal-image] {
  cursor: pointer;
}

.gm-modal {
  display: flex;
  position: fixed;
  justify-content: space-around;
  align-items: center;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  box-sizing: border-box;
  padding: 2rem;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(4px);
  opacity: 0;
  visibility: hidden;
  transition: visibility 0.2s, opacity 0.2s;
}

.gm-modal.active {
  opacity: 1;
  visibility: visible;
}

.gm-modal__overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  cursor: default;
}

.gm-modal__content {
  position: relative;
}

.gm-modal__close {
  position: absolute;
  display: inline-block;
  right: 0;
  top: -4rem;
  border: 0px solid transparent;
  outline: 0;
  padding: 1rem;
  line-height: 1.6rem;
  color: #fff;
  background-color: transparent;
  font-size: 2rem;
  cursor: pointer;
}

.gm-modal__img img {
  width: auto;
  height: auto;
  max-width: calc(100vw - 2rem);
  max-height: calc(100vh - 8rem);
}
```

#最後に
cssは細かくプロパティを設定できていないので、タグ名に直接スタイルを当ててると競合してしまうかもしれない。
フィードバックありがとうございます。