How to stop embed video in Model Popup in Javascript (WooCommerce)?

╄→гoц情女王★ 提交于 2020-07-30 11:45:34

问题


UPDATED

I have used javascript to create a popup and it's working fine. The issue is that i am using iframe embed video code (Facebook) in the model. the model is working fine and on pressing cross button the popup diappears. but the issue is that when used opens popup and play video and then press cross button the video continues to play. The video must stop on pressing cross button. the popup is disappearing but the video plays in background. Another issue is that the FEATURED VIDEO BUTTON appears on all products i want to apply a condition that will show button only if the embed code is added from the backend please guide me how to do that.

HTML CODE (i have added this code after short discription in short-discription.php)

<a href="#jsModal" id="popup" class="jsModalTrigger">FEATURED VIDEO</a>

<div id="jsModal" class="modal">
  <div class="modal__overlay jsOverlay"></div>
  <div class="modal__container">
    <?php
/**
* Single Product Image
*
* This template can be overridden by copying it to yourtheme/woocommerce/single-product/product-image.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see     https://docs.woocommerce.com/document/template-structure/
* @package WooCommerce/Templates
* @version 3.5.1
*/

defined( 'ABSPATH' ) || exit;

// Note: `wc_get_gallery_image_html` was added in WC 3.3.2 and did not exist prior. This check protects against theme overrides being used on older versions of WC.
if ( ! function_exists( 'wc_get_gallery_image_html' ) ) {
    return;
}

global $product;

$columns           = apply_filters( 'woocommerce_product_thumbnails_columns', 4 );
$post_thumbnail_id = $product->get_image_id();
$wrapper_classes   = apply_filters( 'woocommerce_single_product_image_gallery_classes', array(
    'woocommerce-product-gallery',
    'woocommerce-product-gallery--' . ( $product->get_image_id() ? 'with-images' : 'without-images' ),
    'woocommerce-product-gallery--columns-' . absint( $columns ),
    'images',
) );

//for video, need to modify the wrapper classes, as they disable click events
$video_wrapper_classes   = apply_filters( 'woocommerce_single_product_image_gallery_classes', array(
    'woocommerce-product-gallery--' . ( $product->get_image_id() ? 'with-images' : 'without-images' ),
    'woocommerce-product-gallery--columns-' . absint( $columns ),
    'images',
) );

$product_video = get_post_meta(get_the_ID(), 'product_video_field', true );
$product_sub_image = get_the_post_thumbnail($post, [120]);

?>
<div class="<?php echo esc_attr( implode( ' ', array_map( 'sanitize_html_class', $video_wrapper_classes ) ) ); ?>" data-columns="<?php echo esc_attr( $columns ); ?>">
    <figure class="woocommerce-product-gallery__wrapper">
        <?php //if the product video field is not empty, output the video on the page.
            if ( !empty($product_video)) { ?>
                <div id="product-video-container">
                      <?php echo $product_video; ?> 
                </div>
                <!--this is optional, display the featured image below the video, IF there is a video -->

             <?php } else {
                 //if no video, output featured image as per default template
            if ( $product->get_image_id() ) {
            $html = wc_get_gallery_image_html( $post_thumbnail_id, true );
            } else {
            $html = '<div class="woocommerce-product-gallery__image--placeholder">';
            $html .= sprintf( '<img src="%s" alt="%s" class="wp-post-image" />', esc_url( wc_placeholder_img_src( 'woocommerce_single' ) ), esc_html__( 'Awaiting product image', 'woocommerce' ) );
            $html .= '</div>';
            }
        }



        ?>
    </figure>
</div>
    <button class="modal__close jsModalClose">&#10005;</button>
  </div>
</div>

JAVASCRIPT CODE

/* This script supports IE9+ */
(function() {
  /* Opening modal window function */
  function openModal() {
      /* Get trigger element */
      var modalTrigger = document.getElementsByClassName('jsModalTrigger');

      /* Set onclick event handler for all trigger elements */
      for(var i = 0; i < modalTrigger.length; i++) {
          modalTrigger[i].onclick = function() {
            var target = this.getAttribute('href').substr(1);
            var modalWindow = document.getElementById(target);

            modalWindow.classList ? modalWindow.classList.add('open') : modalWindow.className += ' ' + 'open'; 
          }
      }   
  }

  function closeModal(){
    /* Get close button */
    var closeButton = document.getElementsByClassName('jsModalClose');
    var closeOverlay = document.getElementsByClassName('jsOverlay');

    /* Set onclick event handler for close buttons */
      for(var i = 0; i < closeButton.length; i++) {
        closeButton[i].onclick = function() {
          var modalWindow = this.parentNode.parentNode;

          modalWindow.classList ? modalWindow.classList.remove('open') : modalWindow.className = modalWindow.className.replace(new RegExp('(^|\\b)' + 'open'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
        }
      }   

    /* Set onclick event handler for modal overlay */
      for(var i = 0; i < closeOverlay.length; i++) {
        closeOverlay[i].onclick = function() {
          var modalWindow = this.parentNode;

          modalWindow.classList ? modalWindow.classList.remove('open') : modalWindow.className = modalWindow.className.replace(new RegExp('(^|\\b)' + 'open'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
        }
      }  

  }

  /* Handling domready event IE9+ */
  function ready(fn) {
    if (document.readyState != 'loading'){
      fn();
    } else {
      document.addEventListener('DOMContentLoaded', fn);
    }
  }

  /* Triggering modal window function after dom ready */
  ready(openModal);
  ready(closeModal);
}());

function.php CODE:

add_action( 'woocommerce_product_options_general_product_data', 'product_video_field' );
   function product_video_field() {
       $args = array(
           'id'    => 'product_video_field',
           'label'    => sanitize_text_field( 'Product Video' ),
           'placeholder'   => 'Cut and paste video embed code here',
           'desc_tip'    => true,
           'style'    => 'height:120px'

       );
       echo woocommerce_wp_textarea_input( $args );
   }

   add_action( 'woocommerce_process_product_meta', 'product_video_field_save' );


add_action( 'woocommerce_process_product_meta', 'product_video_field_save' );

   function product_video_field_save($post_id) {
       $product_video_field = $_POST['product_video_field'];
       update_post_meta($post_id, 'product_video_field', $product_video_field);
}


回答1:


Without an API provided by the third party, in your case Facebook, there is no way to programmatically communicate through an iframe on a different domain. Therefor it would be easier to create and destroy the iframe when opening and closing the modals.

Remove the iframe from your HTML. Move the src of the iframe to a the modal element and store the value in a data attribute. This enables you to use the value of the attribute whenever you want when creating the iframe.

<a href="#jsModal" id="popup" class="jsModalTrigger">Trigger</a>

<div id="jsModal" class="modal" data-src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FEasternfabricsstore%2Fvideos%2F691828284946045%2F&show_text=0&width=560">
  <div class="modal__overlay jsOverlay"></div>
  <div class="modal__container">
    <button class="modal__close jsModalClose">&#10005;</button>
  </div>
</div>

In your JavaScript create a function which constructs an iframe element with the src and attributes that you currently have in your HTML. This function has to be called whenever the modal is being opened. So it should be called in the onclick event handlers in the openModal function. Append the iframe to the modal__container element and open the modal.

Same goes for the closeModal function where your should remove the iframe element from the HTML to stop the video from playing in the background, which will solve your issue.

In combination with the creation of the iframe you now can start and stop your iframe video on opening and closing the modal.

/* This script supports IE9+ */
(function() {

  function createIframe(src) {
      if (typeof src !== 'string') {
          throw Error('src argument has to be a valid string');
      }
      var iframe = document.createElement('iframe');
      iframe.src = src;
      iframe.width = 560;
      iframe.height = 308;
      iframe.setAttribute('scrolling', 'no');
      iframe.setAttribute('frameBorder', 0);
      iframe.setAttribute('allowTransparency', 'true');
      iframe.setAttribute('allowFullscreen', 'true');
      iframe.style.border = 'none';
      iframe.style.overflow = 'hidden';
      return iframe;
  }

  /* Opening modal window function */
  function openModal() {
      /* Get trigger element */
      var modalTrigger = document.getElementsByClassName('jsModalTrigger');

      /* Set onclick event handler for all trigger elements */
      for(var i = 0; i < modalTrigger.length; i++) {
          modalTrigger[i].onclick = function() {
            var target = this.getAttribute('href').substr(1);
            var modalWindow = document.getElementById(target);
            var source = modalWindow.getAttribute('data-src');
            var iframe = createIframe(source);
            var modalContainer = this.lastElementChild;
            modalContainer.appendChild(iframe);
            modalWindow.classList ? modalWindow.classList.add('open') : modalWindow.className += ' ' + 'open'; 
          }
      }   
  }

  function closeModal(){
    /* Get close button */
    var closeButton = document.getElementsByClassName('jsModalClose');
    var closeOverlay = document.getElementsByClassName('jsOverlay');

    /* Set onclick event handler for close buttons */
      for(var i = 0; i < closeButton.length; i++) {
        closeButton[i].onclick = function() {
          var modalContainer = this.parentNode;
          var modalWindow = modalContainer.parentNode;
          modalContainer.removeChild(modalContainer.firstElementChild);
          modalWindow.classList ? modalWindow.classList.remove('open') : modalWindow.className = modalWindow.className.replace(new RegExp('(^|\\b)' + 'open'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
        }
      }   

    /* Set onclick event handler for modal overlay */
      for(var i = 0; i < closeOverlay.length; i++) {
        closeOverlay[i].onclick = function() {
          var modalWindow = this.parentNode;
          
          modalWindow.classList ? modalWindow.classList.remove('open') : modalWindow.className = modalWindow.className.replace(new RegExp('(^|\\b)' + 'open'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
        }
      }  

  }

  /* Handling domready event IE9+ */
  function ready(fn) {
    if (document.readyState != 'loading'){
      fn();
    } else {
      document.addEventListener('DOMContentLoaded', fn);
    }
  }

  /* Triggering modal window function after dom ready */
  ready(openModal);
  ready(closeModal);
}());

Now your WooCommerce video field is already good, but maybe it's a good idea to indicate that the src of the iframe is needed as value instead of the a complete <iframe> tag. This is because we will be building the iframe on the frontend.

add_action( 'woocommerce_product_options_general_product_data', 'product_video_field' ); 
function product_video_field() { 
    $args = array( 
        'id'            => 'product_video_field', 
        'label'         => sanitize_text_field( 'Product Video' ), 
        'placeholder'   => 'Place embed src value of video here', 
        'desc_tip'      => true, 
        'style'         => 'height: 120px' 
    ); 
    echo woocommerce_wp_textarea_input( $args ); 
} 

add_action( 'woocommerce_process_product_meta', 'product_video_field_save' ); 
function product_video_field_save( $post_id ) { 
    $product_video_field = $_POST[ 'product_video_field' ]; 
    update_post_meta( $post_id, 'product_video_field', $product_video_field ); 
}

Your Single Product Image template is also really close. The only thing that you should modify here is the structure of the modal and the output of the video from WooCommerce. The code below will output the src of the video onto a data-src attribute which will be read by JavaScript when creating the iframe.

/**
* Single Product Image
*
* This template can be overridden by copying it to yourtheme/woocommerce/single-product/product-image.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see     https://docs.woocommerce.com/document/template-structure/
* @package WooCommerce/Templates
* @version 3.5.1
*/

defined( 'ABSPATH' ) || exit;

// Note: `wc_get_gallery_image_html` was added in WC 3.3.2 and did not exist prior. This check protects against theme overrides being used on older versions of WC.
if ( ! function_exists( 'wc_get_gallery_image_html' ) ) {
    return;
}

global $product;

$columns           = apply_filters( 'woocommerce_product_thumbnails_columns', 4 );
$post_thumbnail_id = $product->get_image_id();
$wrapper_classes   = apply_filters( 'woocommerce_single_product_image_gallery_classes', array(
    'woocommerce-product-gallery',
    'woocommerce-product-gallery--' . ( $product->get_image_id() ? 'with-images' : 'without-images' ),
    'woocommerce-product-gallery--columns-' . absint( $columns ),
    'images',
) );

//for video, need to modify the wrapper classes, as they disable click events
$video_wrapper_classes   = apply_filters( 'woocommerce_single_product_image_gallery_classes', array(
    'woocommerce-product-gallery--' . ( $product->get_image_id() ? 'with-images' : 'without-images' ),
    'woocommerce-product-gallery--columns-' . absint( $columns ),
    'images',
) );

$product_video = get_post_meta(get_the_ID(), 'product_video_field', true );
$product_sub_image = get_the_post_thumbnail($post, [120]);

?>
<div class="<?php echo esc_attr( implode( ' ', array_map( 'sanitize_html_class', $video_wrapper_classes ) ) ); ?>" data-columns="<?php echo esc_attr( $columns ); ?>">
    <figure class="woocommerce-product-gallery__wrapper">
        <?php //if the product video field is not empty, output the video on the page.
            if ( !empty($product_video)) { ?>
                <a href="#jsModal" id="popup" class="jsModalTrigger">FEATURED VIDEO</a>

                <div id="jsModal" class="modal" data-src="<?php echo $product_video; ?>">
                    <div class="modal__overlay jsOverlay"></div>
                    <div class="modal__container">
                        <button class="modal__close jsModalClose">&#10005;</button>
                    </div>
                </div>
                <!--this is optional, display the featured image below the video, IF there is a video -->

             <?php } else {
                 //if no video, output featured image as per default template
            if ( $product->get_image_id() ) {
            $html = wc_get_gallery_image_html( $post_thumbnail_id, true );
            } else {
            $html = '<div class="woocommerce-product-gallery__image--placeholder">';
            $html .= sprintf( '<img src="%s" alt="%s" class="wp-post-image" />', esc_url( wc_placeholder_img_src( 'woocommerce_single' ) ), esc_html__( 'Awaiting product image', 'woocommerce' ) );
            $html .= '</div>';
            }
        }

        ?>
    </figure>
</div>
   

I hope it works out. Please let me know if it did.



来源:https://stackoverflow.com/questions/62778904/how-to-stop-embed-video-in-model-popup-in-javascript-woocommerce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!