如何使我的Bootstrap 4弹出点击键盘上的“Esc”键后关闭,而弹出窗口有一个YouTube视频嵌入为iframe并暂停?

axzmvihb  于 2023-04-03  发布在  Bootstrap
关注(0)|答案(1)|浏览(142)

我们使用Bootstrap 4,当点击时会打开一个弹出窗口。弹出窗口中嵌入了一个YouTube视频。只要视频iframe不受干扰,点击“Esc”按钮就会正确关闭视频。但是,如果我们暂停视频或通过点击“Tab”然后点击“Esc”按钮进行交互,则弹出窗口不会关闭。我在HTML,JavaScript,和jQuery版本,它对我不起作用。下面是代码片段。

<a href="#" data-toggle="modal" data-target="#modalVideo" data-keyboard="true"></a>

<section class="">
  <div class="container mx-auto">
    <div class="row">
      <div class="modal fade" id="modalVideo" tabindex="-1" role="dialog" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-body mb-0 p-0">
              <div class="embed-responsive embed-responsive-16by9">
                <iframe class="embed-responsive-item" 
                        src="" allow="accelerometer; autoplay; 
                        encrypted-media; gyroscope; picture-in-picture"  
                        frameborder="0" allowfullscreen></iframe>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

以下是jQuery

var src_culture="https://www.youtube.com/embed/someVideo_x?autoplay=1&enablejsapi=1";
$('#modalVideo').on('hidden.bs.modal', function (e) {
  // do something...
  $('#modalVideo iframe').attr("src", "");
  $("body").css("padding-right","0");
});
$("#modalVideo").on('shown.bs.modal', function(){
  $("#modalVideo iframe").attr('src', src_culture);
  $("body").css("padding-right","0");
});

在与<iframe>交互后,请帮助在单击“Esc”按钮时关闭此弹出窗口。

k3bvogb1

k3bvogb11#

这种行为是有经验的,因为浏览器在点击iframe(在你的例子中是视频)后会聚焦iframe中的元素。当iframe被聚焦时,所有键盘事件都会转到iframe中的代码,而不是你自己的代码。
这并不容易解决,因为iframe引用了另一个服务器,大多数浏览器阻止任何跨源的脚本访问(这是一件安全方面的好事)。YouTube视频不在您的控制之下。然而,有一些策略可以解决这个问题。

重聚焦模态video元素

您可以尝试将焦点带回到您控制的元素,例如#modalVideo元素。

**工作方案:**在下面的代码片段中,我设置了一个间隔,如果当前聚焦的元素是<iframe>,则每隔100 ms重新聚焦到视频模式。因此,焦点再次集中在模式上,这会导致所有预期的引导行为再次工作-包括ESC键关闭模式:

const focusTarget = $("#modalVideo");

setInterval(_ => {
    if (document.activeElement.tagName === "IFRAME") {
        focusTarget.focus();
    }
}, 100);
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#" data-toggle="modal" data-target="#modalVideo" data-keyboard="true">Toggle</a>

<section class="">
  <div class="container mx-auto">
    <div class="row">
      <div class="modal fade" id="modalVideo" tabindex="-1" role="dialog" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-body mb-0 p-0">
              <div class="embed-responsive embed-responsive-16by9">
                <iframe tabindex="-1" width="560" height="315" src="https://www.youtube.com/embed/C7MRkqP5NRI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-pictuare; web-share" allowfullscreen></iframe>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

备选方案

如果你对这个解决方案不满意,你可以尝试使用<object><embed>标签。使用这些标签,你可以编写脚本来将KeyPressEvent传播到父级(视频模式)。然后,它也应该根据 Bootstrap 定义的行为来运行。这是有效的,因为这些标签在你的控制之下,没有跨源策略会干扰它。
您还可以尝试使用一种更复杂的方法来重新关注模态窗口,而不是每隔100 ms轮询一次,尽管这可能并不简单。

一般来说,我建议不要在不需要的时候使用<iframe>,因为它们会带来像您正在经历的那样的复杂问题。

相关问题