Добавление ссылки Vimeo в наш Wordpress сайт Hero Content Block приводит к тому, что вся навигация по основному сайту становится неактивной только в Chrome - PullRequest
0 голосов
/ 22 января 2020

У нас есть сайт Wordpress, который использует пользовательский блок контента для своего баннера героя. У нас есть кнопка, настроенная внутри героя, которая запускает видео с Youtube или Vimeo в Iframe, отображаемом в модальном окне. Однако, если вы сконфигурированы для использования видео Vimeo, при нажатии в любом месте страницы видео VIMEO не запустится. Вместо этого только звук из видео начинает воспроизводиться. Вы можете включить / выключить звук, щелкнув в любом месте страницы (вместо нажатия на кнопку). Кроме того, все вкладки в главной навигации сайта становятся неактивными. Таким образом, вы не можете использовать основную навигацию для перехода с этой страницы. Таким образом, конечный пользователь застревает, слушая аудио из видео, которое он не может видеть, и навигация не доступна.

Вы можете увидеть ошибку в действии, используя Chrome на нашем промежуточном сайте: https://stgkipp.wpengine.com/brand/

Пример страницы с ошибкой

Страница основана на шаблоне, который использует блок Hero, настроенный в WP-Admin. Он имеет кнопку, которая настроена для запуска видео с Youtube или Vimeo. Когда он настроен для ссылки на видео из Vimeo, мы видим ошибку выше (без проблем, если мы выбираем YouTube)

Ниже приведена конфигурация блока контента: [Конфигурация блока контента]

Для рендеринга видео у нас есть скрипт JS. Я включил сценарий JS для Vimeo, так как Youtube, похоже, не является проблемой:

/**
 *
 * Video Service
 *
 * Logic to setup different video iframe api services (currently Youtube and Vimeo)
 *
 * IMPORTANT: IOS devices don't allow you to use the service API to trigger play on the iframe.
 * Instead, allow the user to click directly on the ifram, which will work fine.
 * 
 */

import $ from 'jquery';
import eventBus from './eventBus';
import { loadScriptOnce } from './load';

let playerOrigin = '*';

/**
 *
 * Helper function for sending a message to the vimeo player, taken from {@link Vimeo API}
 * {@link https://developer.vimeo.com/player/js-api Vimeo API}
 * 
 * @param {string} action - Name of the action to be posted to the iframe
 * @param {string} value - Value of the action to be posted to the iframe
 * @param {HTMLIFrameElement} playerIframe - Iframe DOM element of the player
 * 
 */

function postToVimeo(action, value, playerIframe) {

  var data = {
    method: action
  };

  if(value) {
    data.value = value;
  }

  var message = JSON.stringify(data);
  playerIframe.contentWindow.postMessage(message, playerOrigin);
}


/**
 *
 * Listen for 'message' events from the VIMEO iframe, and call the corresponding
 * handler from a provied configuration object
 *
 * @param {object} config - instance configuration object. Must have valid methods
 *                        Corresponding to the Vimeo API events
 * @param {HTMLIframeElement} iframe - Vimeo iframe video player
 *
 */

function initVimeo(config, iframe) {

  window.addEventListener('message', (e) => {

    let data = JSON.parse(e.data);
    
    // Handle messages from the vimeo player only
    if (!(/^https?:\/\/player.vimeo.com/).test(e.origin)) {
      return false;
    }
    
    // Return if the message is not from this iframe
    if(iframe.id !== data.player_id) {
      return false;
    }

    if (playerOrigin === '*') {
      playerOrigin = e.origin;
    }

    // Execute the handler for this event, if it's a valid function
    if(typeof config[data.event] == 'function') {
      config[data.event]()
    }

  }, false);
}


/**
 *
 * Youtube calls this function automatically once the API has loaded
 *
 */

const youtubeAPIPromise = $.Deferred();
window.onYouTubeIframeAPIReady = () => {
  youtubeAPIPromise.resolve();
}


/**
 *
 * Initialize a video service instance. Returns a `serviceController`
 * object for listening to API events  and controlling player with custom elements.
 *
 * @param {string} serviceName - Name of the service to initialize
 * @param {HTMLIframeElement} iframe - Iframe video player
 * @returns {object} serviceController - service video service controller instance.
 */

function initVideoService(serviceName, iframe) {

  let serviceReady = $.Deferred();

  // Instace controller
  let serviceController = {}

  // Since each service has a very different API, 
  // We have to assemble the `serviceController` for each type
  // in a different way, while still providing a consistent interface.
  switch (serviceName) {

    case 'vimeo':

      // Assign the controls methods for vimeo
      serviceController.play = () => {
        serviceReady.then(() => {
          postToVimeo('play', null, iframe);
        })
      }
      serviceController.stop = () => {
        serviceReady.then(() => {
          postToVimeo('pause', null, iframe);
        })
      }

      initVimeo({
        ready() {
          // Need to tell Vimeo that we want to listen for this events
          postToVimeo('addEventListener', 'play', iframe);
          postToVimeo('addEventListener', 'finish', iframe);

          serviceReady.resolve();
        },
        play() {
          eventBus.publish('service:play', iframe)
        },

        finish() {
          eventBus.publish('service:finish', iframe)
        }
      }, iframe)
    break;

    case 'youtube':

      // Assign control methods for youtube
      serviceController.play = () => {
        serviceReady.then((player) => {
          player.playVideo()
        })
      }
      serviceController.stop = () => {
        serviceReady.then((player) => {
          player.stopVideo()
        })
      }

      loadScriptOnce('https://www.youtube.com/iframe_api');

      youtubeAPIPromise.then(() => {
        
        let player = new YT.Player(iframe, {
          events: {
            onReady() {
              serviceReady.resolve(player);
            },
            onStateChange(e) {
              if(e.data == 1) {
                eventBus.publish('service:play', iframe)
              } else if (e.data == 0) {
                eventBus.publish('service:finish', iframe)
              }
            }
          }
        })

      })

    break;
  }

  return serviceController
}

export default initVideoService

Вот файл ветки для Героя, если он вам нужен:

{% if post.hero_title or post.hero_content %}

<section id="hero" class="hero hero--overlay hero--{{ post.hero_media_type }} js-scroll-section js-image-load">

<div class="hero__body">
  <h1 class="hero__title" data-animate="title">{{ post.hero_title }}</h1>

  {% if post.hero_content %}
    <p data-animate="blurb">{{ post.hero_content }}</p>
  {% endif %}

  {% if post.hero_add_button %}

    {% include 'components/button.twig' with {
      addButton: post.get_field( 'hero_add_button' ),
      text: post.get_field( 'hero_button_text' ),
      type: post.get_field( 'hero_button_type' ),
      target: post.get_field( 'hero_button_target_' ~ post.get_field( 'hero_button_type' ) ),
      link: post.get_field( 'hero_button_link_' ~ post.get_field( 'hero_button_type' ) ),
      attribute:  'data-animate="cta"',
      btnAttribute: 'data-toggle-modal="#hero-modal-video"'
    } %}

    {% if post.hero_button_type == 'video' %}
      {% include 'components/modal-video.twig' with {
        id: 'hero-modal-video',
        video_service: post.hero_video_service,
        video_id: post.hero_video_id
      } %}
    {% endif %}

  {% endif %}

  {% if post.hero_media_type == 'video' %}
    <div id="playpause" tabindex="0">
      <button type="button">
        <span class="icon-pause" aria-hidden="true"></span>
        <span class="text"></span>
      </button>
    </div>
  {% endif %}

  </div>
 </div>


 {% if post.hero_media_type == 'video' %}
 <video id="hero-video" class="hero__video js-video-autoplay" autoplay loop>
  <source src="{{ post.get_field('hero_video_webm') }}" type="video/webm">
  <source src="{{ post.get_field('hero_video_mp4') }}" type="video/mp4">
  <source src="{{ post.get_field( 'hero_video_ogv' ) }}" type="video/ogv">
 </video>
{% endif %}

{% if post.hero_add_cta %}
 <div class="hero__action">
  <div class="hero-cta-box hero-cta-box--{{ post.hero_cta_type }}">

    {% if post.hero_cta_header %}
      <h4 class="hero-cta-box__title {{ post.hero_zip_code_description ? 'mb-05'}}">{{ post.hero_cta_header }}</h4>
    {% endif %}

    {% if post.hero_cta_type == 'zip_code' %}

      {% if post.hero_zip_code_description %}
        <p>{{ post.hero_zip_code_description }}</p>
      {% endif %}

      {% include 'components/zip-code.twig' with {
        className: 'form-columns',
        labelColor: 'white',
        btnText: post.hero_cta_button_text
      } %}

    {% else %}

      {% include 'components/button.twig' with {
        addButton: true,
        text: post.get_field( 'hero_cta_button_text' ),
        type: post.get_field( 'hero_cta_button_type' ),
        target: attribute( post, 'button_target_' ~ post.get_field( 'hero_cta_button_type' ) ),
        link: attribute( post, 'button_link_' ~ post.get_field( 'hero_cta_button_type' ) ),
        wrapperClass: 'hero-cta-box__button'
      } %}

    {% endif %}

   </div>
  </div>
{% endif %}

</section><!-- .hero -->

{% endif %}

Пожалуйста, дайте мне знать, будет ли полезна любая другая информация.

...