javascript Issue319:20171101 - バナーとモーダルとAMP

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript Issue319:20171101 - バナーとモーダルとAMP相关的知识,希望对你有一定的参考价值。

import forEach from 'lodash/forEach'
import { hasClass } from '../utils/DOM'
import { setLocalStLimit } from './yearEndBanner'

const pageDOM = document.getElementById('page')
const modalImgAbsolutePath = '/r/bnr/point/year-end-cpn201710_sp.png'

const buildElement = (elmDataObj) => {
  const elm = document.createElement(elmDataObj.tagName)
  forEach(elmDataObj, (value, key) => {
    if (key === 'tagName') return
    if (key === 'text') {
      elm.appendChild(document.createTextNode(elmDataObj[key]))
    } else {
      elm[key] = elmDataObj[key]
    }
  })
  return elm
}

// 忘年会CPモーダルを作り出し、最親DOMを返す関数.
// 引数で現在ページを判定し、予約ページで発火する場合、リンク要素無しのモーダルが生成される。
const modalBuild = (isReserve) => {
  const divYearEndModal = buildElement({ tagName: 'div', id: 'js-year-end_modal', className: 'year-end_modal js-modal-close' })
  const divContentWrap = buildElement({ tagName: 'div', className: 'year-end_modal__content-wrap' })
  const divModalContent = buildElement({ tagName: 'div', className: 'year-end_modal__content' })
  const divImgWrap = buildElement({ tagName: 'div', className: 'img-wrap' })
  const imgItem = buildElement({ tagName: 'img', className: 'img-item', src: modalImgAbsolutePath, alt: '2017年度忘年会予約キャンペーン' })

  const divLinkArea = buildElement({ tagName: 'div', className: 'link-area' })
  const aLink = buildElement({ tagName: 'a', className: 'link', text: '利用規約・詳細はこちら', href: '/sp/campaign/enkai_10/s/?sc_lid=enkaicp_tnp_12' })
  const divCloseBtnArea = buildElement({ tagName: 'div', className: 'close-btn-area' })
  const spnaCloseBtn = buildElement({ tagName: 'span', className: 'close-btn js-modal-close', text: '閉じる' })

  const divNodeArr = [divYearEndModal, divContentWrap, divModalContent, divImgWrap, imgItem]
  const linkNodeArr = [divImgWrap, divLinkArea, aLink]
  const closeAreaArr = [divModalContent, divCloseBtnArea, spnaCloseBtn]

  // ""Element配列の配列"""を渡すと渡された順番通りにDOMを整形する関数.
  const shapingDOM = elmArr => elmArr.forEach(nodeArr => nodeArr.reduce((parent, child) => parent.appendChild(child)))

  // 予約ページ内でこの関数が発火していたら、(離脱率防止のために)リンクのないモーダルを作り出す.
  if (isReserve) {
    shapingDOM([divNodeArr, closeAreaArr])
  } else {
    shapingDOM([divNodeArr, linkNodeArr, closeAreaArr])
  }

  // 整形されたDOMの最も親となるElementを返す.
  return divYearEndModal
}

export function yearEndModal() {
  const bannerDOM = document.getElementById('js-year-end-banner')
  const modalTrigger = document.getElementsByClassName('js-year-end-modal-trigger')
  const isReservePage = document.getElementsByClassName('js-reserve-page-flag')[0] !== undefined
  // 表示したhtmlにモーダルのトリガーがなければこの関数は役目終了.
  if (!modalTrigger) return

  forEach(modalTrigger, (mTrigger) => {
    mTrigger.addEventListener('click', (ev) => {
      // aタグにラップされてたとき用のpreventDefault()
      ev.preventDefault()

      // バナーからこのモーダルが発火しているか判定.
      if (hasClass(mTrigger, 'year-end-sticky__item')) {
        bannerDOM.parentNode.removeChild(bannerDOM)
        setLocalStLimit('bannerHide')
      }

      // 予約ページなら他ページへのリンクのないモーダルをビルドしてappend.
      pageDOM.appendChild(modalBuild(isReservePage))

      // appendしたDOM情報を取得.
      const modalDOM = document.getElementById('js-year-end_modal')
      const closeModalTrigger = document.getElementsByClassName('js-modal-close')

      // モーダル出現後に黒枠を押下したか、閉じるボタンを押下したか判定する.
      forEach(closeModalTrigger, (closeTrigger) => {
        closeTrigger.addEventListener('click', (e) => {
          if (hasClass(e.target, 'js-modal-close')) {
            modalDOM.parentNode.removeChild(modalDOM)
            // 貫通して背景までクリックさせるのを防止する.
            e.stopPropagation()
          }
        })
      })
    })
  })
}

// AMPページからの遷移時

// yearEndModal()から必要な部分のみコピペでモーダルの流用
function yearEndModalAMP() {
  pageDOM.appendChild(modalBuild())

  const modalDOM = document.getElementById('js-year-end_modal')
  const closeModalTrigger = document.getElementsByClassName('js-modal-close')

  forEach(closeModalTrigger, (closeTrigger) => {
    closeTrigger.addEventListener('click', (e) => {
      if (hasClass(e.target, 'js-modal-close')) {
        modalDOM.parentNode.removeChild(modalDOM)
        e.stopPropagation()
      }
    })
  })
}

// ページ内のelmのY座標
const getTargetPositionY = (elm) => {
  const rect = elm.getBoundingClientRect()
  return rect.top + pageYOffset
}

// ハッシュでAMPからの遷移を判別してモーダルを開く
export const judgeAMPModal = () => {
  const ampHash = location.hash

  if (ampHash.match('#amp-campaign')) {
    const campaignBanner = document.querySelector('.js-year-end-modal-trigger.-block')
    const campaignBannerSection = campaignBanner.parentNode.parentNode
    const positionX = 0
    const positionY = getTargetPositionY(campaignBannerSection)

    window.scrollTo(positionX, positionY)
    location.hash = '_'
    yearEndModalAMP()
  }
}
import { yearEndBanner } from './yearEndBanner'
import { yearEndModal, judgeAMPModal } from './yearEndModal'

export default function yearendPartyCp() {
  yearEndBanner()
  yearEndModal()
  judgeAMPModal()
}

以上是关于javascript Issue319:20171101 - バナーとモーダルとAMP的主要内容,如果未能解决你的问题,请参考以下文章

javascript Issue84 - 20190620电话导线改善

javascript LRM_BP_issue

javascript Issue302:20171018 - 动画商品トライアル

javascript Issue15:20180705 - no79.CVエリア改善

javascript Issue30:20180920 - no82。他店铺リンク设置

javascript Issue345:20180130 - no63。ナビゲーションに「地図」追加