如何检查添加的 class 是否有视频然后播放

How to check if an added class has a video and then play it

我有一个 jQuery 函数,它从元素中删除 class,然后将 class 添加到列表中的下一个元素。

<div class="slider-slide-wrap has-data multi first-item-is-video shown">
<ul class="multi-items">
  <li class="single-data-item active"></li>
  <li class="single-data-item item-is-video"><video id="video-post">video</video></li>
  <li class="single-data-item item-is-social"></li>
  <li class="single-data-item item-is-social"></li>
  <li class="single-data-item item-is-website"></li>
  <li class="single-data-item item-is-website"></li>
  <li class="single-data-item item-is-video"><video id="video-post">video</video></li>
</ul>
</div>

该函数通过单击一个按钮来工作,它从 li 中删除 .active,并将 .active 添加到下一个 li

我遇到的问题是 class .item-is-video。那些有视频文件,当它们被选中时,它们会播放所有视频。我正在尝试找到一种在单击按钮时播放视频的方法,以便当 .active 被删除并添加到下一个 li 时,如果 .item-is-video.active然后播放视频。它要么播放所有视频,要么播放其中 none 个视频。

我的问题是,我正在寻找一种仅在 .active.item-is-video 且只有该视频的情况下播放视频的方法。

我的代码:

$('#multi-start-video,#multi-next-item-video').click(function() {
         if($('.first-item-is-video.shown .multi-items li:first-child').is(':visible')) {
           $('#multi-start-video').css('display','none');
           $('#multi-next-item-video').css('display','block');
         } else {
           $('#multi-start-video').css('display','none');
           $('#multi-next-item-video').css('display','block');
         }
         let $item;
         if(!$('.first-item-is-video.shown ul.multi-items li.single-data-item.active').length) {
             $item = $('.first-item-is-video.shown ul.multi-items li.single-data-item').first();
         }
         else {
            $prev = $('.first-item-is-video.shown ul.multi-items li.single-data-item.active');
            $item = $prev.next();
      
            if(!$prev.next().length) {
                $prev.removeClass('active');
                $prev.fadeOut(5);
                return;
            }
      
            $prev.removeClass('active');
            $prev.fadeOut(5);
        }
        if($($item).is('.item-is-video')) {
            $('video#video-post').trigger('play');
        }
      
        $item.addClass('active');
        $item.fadeIn(5);
        });
    .single-data-item {display:none}
    video {width:320px;height:auto}
    .single-data-item li {  list-style-type: none}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="multi-next-item-video" class="button">Next item</button>
        

    <div class="slider-slide-wrap has-data multi first-item-is-video shown">
        <ul class="multi-items">
          <li class="single-data-item active"></li>
          <li class="single-data-item item-is-video"><video id="video-post" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4"></video></li>
          <li class="single-data-item item-is-social">item 2</li>
          <li class="single-data-item item-is-social">item 3</li>
          <li class="single-data-item item-is-website">item 4</li>
          <li class="single-data-item item-is-website">item 5</li>
          <li class="single-data-item item-is-video"><video id="video-post" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"></video></li>
        </ul>
        </div>

您只需要使用 $item.find() select 视频。

因此只会播放 selected 的视频。您也可以在点击开始时使用 $('video').trigger('pause') 以在切换到下一个项目时停止每个视频。

编辑:$('video#video-post') select id="video-post" 的所有视频。所以他们都玩。 .find() 只会 select $item 的子项。

您可以在此处阅读有关 .find() 的更多信息:https://api.jquery.com/find/

$('#multi-start-video,#multi-next-item-video').click(function() {
         $('video').trigger('pause');
         if($('.first-item-is-video.shown .multi-items li:first-child').is(':visible')) {
           $('#multi-start-video').css('display','none');
           $('#multi-next-item-video').css('display','block');
         } else {
           $('#multi-start-video').css('display','none');
           $('#multi-next-item-video').css('display','block');
         }
         let $item;
         if(!$('.first-item-is-video.shown ul.multi-items li.single-data-item.active').length) {
             $item = $('.first-item-is-video.shown ul.multi-items li.single-data-item').first();
         }
         else {
            $prev = $('.first-item-is-video.shown ul.multi-items li.single-data-item.active');
            $item = $prev.next();
      
            if(!$prev.next().length) {
                $prev.removeClass('active');
                $prev.fadeOut(5);
                return;
            }
      
            $prev.removeClass('active');
            $prev.fadeOut(5);
        }

        
        if($($item).is('.item-is-video')) {
            $item.find('video#video-post').trigger('play');
        }
      
        $item.addClass('active');
        $item.fadeIn(5);
        });
    .single-data-item {display:none}
    video {width:320px;height:auto}
    .single-data-item li {  list-style-type: none}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="multi-next-item-video" class="button">Next item</button>
        

    <div class="slider-slide-wrap has-data multi first-item-is-video shown">
        <ul class="multi-items">
          <li class="single-data-item active"></li>
          <li class="single-data-item item-is-video"><video id="video-post" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4"></video></li>
          <li class="single-data-item item-is-social">item 2</li>
          <li class="single-data-item item-is-social">item 3</li>
          <li class="single-data-item item-is-website">item 4</li>
          <li class="single-data-item item-is-website">item 5</li>
          <li class="single-data-item item-is-video"><video id="video-post" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"></video></li>
        </ul>
        </div>

#id 必须是唯一的

首先,#id 必须是唯一的,这条基本重要的规则没有例外。因此,将 #video-post 更改为 #video-post1#video-post2...更好的是在两者上都使用 .video-post class。


取消引用 jQuery 对象

<video> 标签由 Video API 控制,这是一个普通的 JavaScript 界面。虽然jQuery本质上是JavaScript,但jQ无法识别.play().pause()等普通JS方法。虽然使用 .trigger() 方法触发事件是可行的,但它不能很好地替代视频 API 提供的控件。

为了在元素上使用普通 JavaScript 方法,它必须作为 DOM 对象而不是 jQuery 对象引用。当然使用普通的 JS 方法,例如:

const active = document.querySelector('.active'); 
let vid = active.querySelector('video'); 

如果您已经拥有,那就是臃肿:

let $vid = $('.active').find('video');

幸运的是,有两种简单的方法可以将 jQuery 对象转换为 DOM 对象。该术语称为取消引用。继续上面的例子:

  1. 括号表示法

    $vid[0]
    
  2. .get()方法

    $vid.get(0);
    

其中一个就足够了(它们是等价的)。


演示

下面的演示只是对 jQuery 的简化高效使用。仅建议您遵循以下代码和样式:

  • 少class有
  • 没有 ID
  • 使用this关键字
  • 条件流
  • 索引位置的使用
  • 使用更合适的jQuery方法
  • 事件委托
  • 互斥模式

这个列表还在继续,并且对这些要点中的任何一个进行详细说明都会避开这个问题。尝试演示,尽可能多地应用到您自己的代码中。所有细节都在演示中进行了评论。祝你好运。

/*
The next 3 statements are one time initialization steps
- declare index count
- hide al <li> except the active one
- hide all videos (this is done separately for the FX)
*/
let index = 0;
$('.items li').not('.active').hide();
$('video').hide();

/*
click event is delegated to <nav>
any <button> clicked by user is considered "this" (also e.target)
*/
$('.navbar').on('click', 'button', function(e) {

  // Declare the last <li> index number 
  const last = $('.items li').length - 1;
  //console.log(last);
  /*
  These control statements establish:
  - if the index number increases or decreases by 1
    according to which <button> was clicked
  - to cycle as a bi-directional loop
  Normally I would use ternary for terseness and less
  bloat but I used if/else if/else for readability instead
  */
  if ($(this).hasClass('next')) {
    index++
    if (index > last) {
      index = 0;
    }
  } else {
    index--;
    if (index < 0) {
      index = last;
    }
  }
  //console.log(index);
  /*
  The next two statements will hide ALL <li> and <video>
  tags and ensuring that nothing has the .active class.
  NOTE: The last statement is this.pause()
        .pause() is a plain JavaScript method thus does not
        recognize jQuery objects like $(this) so `this`
        keyword must be used instead
  */
  $('.items li').removeClass('active').fadeOut('slow');
  $('video').each(function(i) {
    $(this).slideUp();
    this.pause();
  });

  /*
  Assign the .active class to the <li> at the position 
  designated by current index number
  */
  $('.items li').eq(index).addClass('active');

  /*
  if current active <li> has the .vid class, reveal <li>
  and <video> separately for FX...
  otherwise just reveal the active <li>
  
  NOTE: The statement: vid[0].play();
        .play() is a plain JS method like .pause() and the 
        variable `$vid` references a jQuery object so $vid
        must be de-referenced to be a DOM object that
        .play() will recognize.
        De-referencing a jQ object can be done by:
        - bracket notation: ex. $vid[0]
        or
        - .get() method: ex. $vid.get(0)
        The index number of 0 is required (first reference)
  */
  if ($('.active').hasClass('vid')) {
    let $vid = $('.active').find('video');
    $('.active').fadeIn('fast');
    $vid.slideDown('slow');
    $vid[0].play();
  } else {
    $('.active').fadeIn('slow');
  }

  /*
  There are three actions requested:
  - stop click event from bubbling*
  - prevent any default actions that clicking could
    cause*
  - terminate function
  *the first two above only happen with jQuery
  */
  return false;
});
::root,
body {
  font: 400 3vw/1 Arial;
}

.ui {
  max-width: 420px;
  margin: 5vh auto;
}

.navbar {
  text-align: center
}

.items {
  position: relative;
  list-style: none;
  padding-left: 0
}

button {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer
}

.items li {
  position: absolute;
  top: 0;
  left: 0;
}

.ico {
  font-size: 2.25rem
}

.ico::before {
  content: attr(data-ico);
  display: inline-block;
  vertical-align: top;
}

video {
  width: 360px;
  height: auto
}
<form class="ui">
  <nav class='navbar'>
    <button class="ico prev" type='button'>⏪</button>
    <button class="ico next" type='button'>⏩</button>
  </nav>
  <ul class="items">
    <li class="ico active" data-ico=''><a href='#/'>Home</a></li>
    <li class='ico' data-ico=''><a href='#/'>Favorites</a></li>
    <li class='ico vid' data-ico=''>
      <video src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4"></video>
    </li>
    <li class='ico' data-ico=''><a href='#/'>Top Topics</a></li>
    <li class='ico' data-ico=''><a href='#/'>Hot Topics</a></li>
    <li class='ico vid' data-ico=''>
      <video src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"></video>
    </li>
  </ul>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>