packages/mip/src/components/mip-shell/switchPage.js
function backwardTransitionAndCreate (shell, options) {
  let {
    targetPageId,
    targetPageMeta,
    sourcePageId,
    sourcePageMeta,
    onComplete
  } = options
  // Goto root page, resume scroll position (Only appears in backward)
  let rootPageScrollPosition = 0
  fixRootPageScroll(shell, {targetPageId})
  if (targetPageId === window.MIP.viewer.page.pageId) {
    rootPageScrollPosition = shell.rootPageScrollPosition
  }

  let iframe = getIFrame(sourcePageId)
  // If source page is root page, skip transition
  if (!iframe) {
    document.documentElement.classList.add('mip-no-scroll')
    window.MIP.viewer.page.getElementsInRootPage().forEach(e => e.classList.add('hide'))

    onComplete && onComplete()

    let targetIFrame = getIFrame(targetPageId)
    if (targetIFrame) {
      activeZIndex -= 2
      css(targetIFrame, 'z-index', activeZIndex++)
    }

    shell.afterSwitchPage(options)
    return
  }

  // Moving out only needs header, not loading body
  let loading = getLoading(sourcePageMeta, {
    onlyHeader: true,
    transitionContainsHeader: shell.transitionContainsHeader
  })
  let headerLogoTitle
  let fadeHeader

  if (shell.transitionContainsHeader) {
    css(loading, 'display', 'block')
  } else {
    headerLogoTitle = document.querySelector('.mip-shell-header-wrapper .mip-shell-header-logo-title')
    headerLogoTitle && headerLogoTitle.classList.add('fade-out')
    fadeHeader = getFadeHeader(targetPageMeta, sourcePageMeta)
    css(fadeHeader, 'display', 'block')
  }

  iframe.classList.add('slide-leave', 'slide-leave-active')
  if (shell.transitionContainsHeader) {
    loading.classList.add('slide-leave', 'slide-leave-active')
  } else {
    fadeHeader.classList.add('fade-enter', 'fade-enter-active')
  }

  // trigger layout and move current iframe to correct position
  /* eslint-disable no-unused-expressions */
  css(iframe, {
    opacity: 1,
    top: rootPageScrollPosition + 'px'
  })
  /* eslint-enable no-unused-expressions */

  whenTransitionEnds(iframe, 'transition', () => {
    css(iframe, {
      display: 'none',
      'z-index': 10000,
      top: 0
    })
    iframe.classList.remove('slide-leave-to', 'slide-leave-active')
    if (shell.transitionContainsHeader) {
      loading.classList.remove('slide-leave-to', 'slide-leave-active')
      css(loading, 'display', 'none')
    } else {
      fadeHeader.classList.remove('fade-enter-to', 'fade-enter')
    }

    onComplete && onComplete()

    let targetIFrame = getIFrame(targetPageId)
    if (targetIFrame) {
      activeZIndex -= 2
      css(targetIFrame, 'z-index', activeZIndex++)
    }

    shell.afterSwitchPage(options)
  })

  nextFrame(() => {
    iframe.classList.add('slide-leave-to')
    iframe.classList.remove('slide-leave')
    if (shell.transitionContainsHeader) {
      loading.classList.add('slide-leave-to')
      loading.classList.remove('slide-leave')
    } else {
      fadeHeader.classList.add('fade-enter-to')
      fadeHeader.classList.remove('fade-enter')
    }
  })
}
function backwardTransitionAndCreate (shell, options) {
  let {
    targetPageId,
    targetPageMeta,
    sourcePageId,
    sourcePageMeta,
    onComplete
  } = options
  // Goto root page, resume scroll position (Only appears in backward)
  let rootPageScrollPosition = 0
  fixRootPageScroll(shell, {targetPageId})
  if (targetPageId === window.MIP.viewer.page.pageId) {
    rootPageScrollPosition = shell.rootPageScrollPosition
  }

  let iframe = getIFrame(sourcePageId)
  // If source page is root page, skip transition
  if (!iframe) {
    document.documentElement.classList.add('mip-no-scroll')
    window.MIP.viewer.page.getElementsInRootPage().forEach(e => e.classList.add('hide'))

    onComplete && onComplete()

    let targetIFrame = getIFrame(targetPageId)
    if (targetIFrame) {
      activeZIndex -= 2
      css(targetIFrame, 'z-index', activeZIndex++)
    }

    shell.afterSwitchPage(options)
    return
  }

  // Moving out only needs header, not loading body
  let loading = getLoading(sourcePageMeta, {
    onlyHeader: true,
    transitionContainsHeader: shell.transitionContainsHeader
  })
  let headerLogoTitle
  let fadeHeader

  if (shell.transitionContainsHeader) {
    css(loading, 'display', 'block')
  } else {
    headerLogoTitle = document.querySelector('.mip-shell-header-wrapper .mip-shell-header-logo-title')
    headerLogoTitle && headerLogoTitle.classList.add('fade-out')
    fadeHeader = getFadeHeader(targetPageMeta, sourcePageMeta)
    css(fadeHeader, 'display', 'block')
  }

  iframe.classList.add('slide-leave', 'slide-leave-active')
  if (shell.transitionContainsHeader) {
    loading.classList.add('slide-leave', 'slide-leave-active')
  } else {
    fadeHeader.classList.add('fade-enter', 'fade-enter-active')
  }

  // trigger layout and move current iframe to correct position
  /* eslint-disable no-unused-expressions */
  css(iframe, {
    opacity: 1,
    top: rootPageScrollPosition + 'px'
  })
  /* eslint-enable no-unused-expressions */

  whenTransitionEnds(iframe, 'transition', () => {
    css(iframe, {
      display: 'none',
      'z-index': 10000,
      top: 0
    })
    iframe.classList.remove('slide-leave-to', 'slide-leave-active')
    if (shell.transitionContainsHeader) {
      loading.classList.remove('slide-leave-to', 'slide-leave-active')
      css(loading, 'display', 'none')
    } else {
      fadeHeader.classList.remove('fade-enter-to', 'fade-enter')
    }

    onComplete && onComplete()

    let targetIFrame = getIFrame(targetPageId)
    if (targetIFrame) {
      activeZIndex -= 2
      css(targetIFrame, 'z-index', activeZIndex++)
    }

    shell.afterSwitchPage(options)
  })

  nextFrame(() => {
    iframe.classList.add('slide-leave-to')
    iframe.classList.remove('slide-leave')
    if (shell.transitionContainsHeader) {
      loading.classList.add('slide-leave-to')
      loading.classList.remove('slide-leave')
    } else {
      fadeHeader.classList.add('fade-enter-to')
      fadeHeader.classList.remove('fade-enter')
    }
  })
}
function backwardTransitionAndCreate ( shell , options ) { let { targetPageId , targetPageMeta , sourcePageId , sourcePageMeta , onComplete } = options // Goto root page, resume scroll position (Only appears in backward) let rootPageScrollPosition = 0 fixRootPageScroll ( shell , { targetPageId } ) if ( targetPageId === window . MIP . viewer . page . pageId ) { rootPageScrollPosition = shell . rootPageScrollPosition } let iframe = getIFrame ( sourcePageId ) // If source page is root page, skip transition if ( ! iframe ) { document . documentElement . classList . add ( 'mip-no-scroll' ) window . MIP . viewer . page . getElementsInRootPage ( ) . forEach ( e => e . classList . add ( 'hide' ) ) onComplete && onComplete ( ) let targetIFrame = getIFrame ( targetPageId ) if ( targetIFrame ) { activeZIndex -= 2 css ( targetIFrame , 'z-index' , activeZIndex ++ ) } shell . afterSwitchPage ( options ) return } // Moving out only needs header, not loading body let loading = getLoading ( sourcePageMeta , { onlyHeader : true , transitionContainsHeader : shell . transitionContainsHeader } ) let headerLogoTitle let fadeHeader if ( shell . transitionContainsHeader ) { css ( loading , 'display' , 'block' ) } else { headerLogoTitle = document . querySelector ( '.mip-shell-header-wrapper .mip-shell-header-logo-title' ) headerLogoTitle && headerLogoTitle . classList . add ( 'fade-out' ) fadeHeader = getFadeHeader ( targetPageMeta , sourcePageMeta ) css ( fadeHeader , 'display' , 'block' ) } iframe . classList . add ( 'slide-leave' , 'slide-leave-active' ) if ( shell . transitionContainsHeader ) { loading . classList . add ( 'slide-leave' , 'slide-leave-active' ) } else { fadeHeader . classList . add ( 'fade-enter' , 'fade-enter-active' ) } // trigger layout and move current iframe to correct position /* eslint-disable no-unused-expressions */ css ( iframe , { opacity : 1 , top : rootPageScrollPosition + 'px' } ) /* eslint-enable no-unused-expressions */ whenTransitionEnds ( iframe , 'transition' , ( ) => { css ( iframe , { display : 'none' , 'z-index' : 10000 , top : 0 } ) iframe . classList . remove ( 'slide-leave-to' , 'slide-leave-active' ) if ( shell . transitionContainsHeader ) { loading . classList . remove ( 'slide-leave-to' , 'slide-leave-active' ) css ( loading , 'display' , 'none' ) } else { fadeHeader . classList . remove ( 'fade-enter-to' , 'fade-enter' ) } onComplete && onComplete ( ) let targetIFrame = getIFrame ( targetPageId ) if ( targetIFrame ) { activeZIndex -= 2 css ( targetIFrame , 'z-index' , activeZIndex ++ ) } shell . afterSwitchPage ( options ) } ) nextFrame ( ( ) => { iframe . classList . add ( 'slide-leave-to' ) iframe . classList . remove ( 'slide-leave' ) if ( shell . transitionContainsHeader ) { loading . classList . add ( 'slide-leave-to' ) loading . classList . remove ( 'slide-leave' ) } else { fadeHeader . classList . add ( 'fade-enter-to' ) fadeHeader . classList . remove ( 'fade-enter' ) } } ) }
Backward transition and create new iframe

@param {Object} shell shell instance
@param {Object} options
@param {string} options.targetPageId targetPageId
@param {Object} options.targetPageMeta pageMeta of target page
@param {string} options.sourcePageId sourcePageId
@param {Object} options.sourcePageMeta pageMeta of source page
@param {boolean} options.newPage whether a new iframe should be created (true)
@param {boolean} options.isForward whether transition direction is forward (false)
@param {Function} options.onComplete complete callback
Backward transition and create new iframe