【问题标题】:How to stop embed video in Model Popup in Javascript (WooCommerce)?如何停止在 Javascript (WooCommerce) 中的模态弹出窗口中嵌入视频?
【发布时间】:2026-02-13 16:40:01
【问题描述】:

更新

我使用 javascript 创建了一个弹出窗口,它工作正常。问题是我在模型中使用 iframe 嵌入视频代码(Facebook)。该模型工作正常,按下十字按钮弹出窗口消失。但问题是,当使用时打开弹出窗口并播放视频,然后按十字按钮,视频会继续播放。视频必须在按下十字按钮时停止。弹出窗口正在消失,但视频在后台播放。另一个问题是 FEATURED VIDEO BUTTON 出现在我想要应用的所有产品上,该条件仅在从后端添加嵌入代码时才会显示按钮,请指导我如何做到这一点。

HTML 代码(我在 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 代码

/* 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 代码:

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);
}

【问题讨论】:

  • 好吧,你无法控制&lt;iframe&gt;元素内部发生的事情,但是你可以在打开和关闭模式窗口时创建和销毁元素。你同意吗?
  • 是的,我不在乎,我只是希望它在关闭弹出窗口时停止

标签: javascript php wordpress model popup


【解决方案1】:

如果没有第三方提供的 API,例如 Facebook,就无法通过不同域上的 iframe 以编程方式进行通信。因此在打开和关闭 modals 时创建和销毁 iframe 会更容易。

从您的 HTML 中删除 iframe。将 iframe 的 src 移动到模态元素并将值存储在 数据属性 中。这使您可以在创建 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>

在您的 JavaScript 中创建一个函数,该函数使用您当前在 HTML 中拥有的 src 和属性构造一个 iframe 元素。每当打开模式时,都必须调用此函数。所以它应该在openModal 函数的onclick 事件处理程序中调用。将 iframe 附加到 modal__container 元素并打开模式。

closeModal 函数也是如此,您应该从 HTML 中删除 iframe 元素以阻止视频在后台播放,这将解决您的问题。

结合 iframe 的创建,您现在可以在打开和关闭模式时启动和停止 iframe 视频。

/* 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);
}());

现在您的 WooCommerce 视频字段已经很好了,但最好指出 iframe 的 src 需要作为值而不是完整的 &lt;iframe&gt; 标记。这是因为我们将在前端构建 iframe。

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 ); 
}

您的单一产品图片模板也非常接近。您应该在此处修改的唯一内容是模式的结构和 WooCommerce 的视频输出。下面的代码会将视频的src 输出到data-src 属性中,JavaScript 在创建 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>
   

我希望它成功了。如果有请告诉我。

【讨论】:

  • Emiel Zuurbier 我已经编辑了这篇文章,实际上我认为只有 Javascript 代码会有变化。我不知道在 PHP 中应用这些更改你能帮我吗??
  • 当然可以。但是现在你的一些课程已经改变了。你能举个例子说明呈现的 HTML 的样子吗?在 WP 管理员中,您将整个 iframe 作为产品视频传递,但您只需要 src。 ;)
  • 是的,我只想传递网址,但我在互联网上找到了这段代码,这就是它的工作原理。我在下面提供了一个产品链接,您可以通过单击精选视频按钮 waqasyousuf.com/tanew/product/elan-lawn-2020 来查看它现在是如何工作的
  • 请指导我。谢谢
  • 还在等你的答复