text: Element.prototype.appendAfter = function(element) {
    element.parentNode.insertBefore(this, element.nextSibling)
  }
  
  function noop() {}
  
  function _createModalFooter(buttons = []) {
    if (buttons.length === 0) {
      return document.createElement('div')
    }
  
    const wrap = document.createElement('div')
    wrap.classList.add('modal-footer')
  
    buttons.forEach(btn => {
      const $btn = document.createElement('button')
      $btn.textContent = btn.text
      $btn.classList.add('btn-modal')
      $btn.classList.add(`btn-modal-${btn.type || 'secondary'}`)
      $btn.onclick = btn.handler || noop
  
      wrap.appendChild($btn)
    })
  
    return wrap
  }
  
  
  function _createModal(options) {
    const DEFAULT_WIDTH = '600px'
    const DEFAULT_TITLE = ''
    const modal = document.createElement('div')
    modal.classList.add('vmodal')
    modal.insertAdjacentHTML('afterbegin', `
      ${options.shadow ? `<div class="modal-overlay" data-close="true">` : `<div class="modal-overlay modal-overlay_shadow_none" data-close="true">`}
        <div class="modal-window" style="max-width: ${options.maxWidth || DEFAULT_WIDTH}">
          ${options.headerBlock ? `<div class="modal-header modal-header_low-height_none">` : `<div style="display: none" class="modal-header modal-header_low-height_none">` }
            <span class="modal-title">${options.title || DEFAULT_TITLE}</span>
            ${options.closable ? `<span class="modal-close" data-close="true">&times;</span>` : ''}
          </div>
          <div class="modal-body" data-content>
            ${options.content || ''}
          </div>
        </div>
      </div>
    `)
    const footer = _createModalFooter(options.footerButtons)
    footer.appendAfter(modal.querySelector('[data-content]'))
    document.body.appendChild(modal)
    return modal
  }
  
  $.modal = function(options) {
    const ANIMATION_SPEED = 200
    const $modal = _createModal(options)
    let closing = false
    let destroyed = false
  
    const modal = {
      open() {
        if (destroyed) {
          return console.log('Modal is destroyed')
        }
        !closing && $modal.classList.add('open')
      },
      close() {
        closing = true
        $modal.classList.remove('open')
        $modal.classList.add('hide')
        setTimeout(() => {
          $modal.classList.remove('hide')
          closing = false
          if (typeof options.onClose === 'function') {
            options.onClose()
          }
        }, ANIMATION_SPEED)
      }
    }
  
    const listener = event => {
      if (event.target.dataset.close) {
        modal.close()
      }
    }
  
    $modal.addEventListener('click', listener, {passive: true})
  
    return Object.assign(modal, {
      destroy() {
        $modal.parentNode.removeChild($modal)
        $modal.removeEventListener('click', listener)
        destroyed = true
      },
      setContent(html) {
        $modal.querySelector('[data-content]').innerHTML = html
      }
    })
  }
  