Как проверить, есть ли у добавленного класса видео, а затем воспроизвести его - PullRequest
2 голосов
/ 24 января 2020

У меня есть функция jQuery, которая удаляет класс из элемента, а затем добавляет класс к следующему элементу в списке.

<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>

Функция работает, нажимая кнопку, и удаляет .active из li и добавляет .active к следующему li.

У меня проблемы с классом .item-is-video. У них есть видео файлы, и когда они выбраны, они воспроизводят все видео. Я пытаюсь найти способ воспроизвести видео при нажатии кнопки, чтобы при удалении .active и добавлении к следующему li, если .item-is-video было .active, воспроизводить видео. Он либо воспроизводит все видео, либо ни одного из них.

Мой вопрос заключается в том, что я ищу способ воспроизвести видео, только если .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>

Ответы [ 2 ]

2 голосов
/ 24 января 2020

Вам просто нужно выбрать видео с помощью $ item.find ().

, поэтому будет воспроизводиться только выбранное видео. Вы также можете использовать $('video').trigger('pause') в начале щелчка, чтобы остановить каждое видео при переходе к следующему элементу.

Редактировать: $('video#video-post') выбрать все видео с id = "video-post". Так что все они играют. .find() выберет только дочерний элемент $ 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>
0 голосов
/ 25 января 2020

# id ДОЛЖЕН быть уникальным

Прежде всего, # id ДОЛЖЕН быть уникальным , нет исключений из этого принципиально важного правила. Так что измените #video-post на #video-post1 и #video-post2 ... еще лучше, просто используйте класс .video-post на обоих.


Разыменование jQuery Объекты

Тег <video> управляется Видео API , который является простым JavaScript интерфейсом. Хотя jQuery по сути JavaScript, jQ не может распознать простые JS методы, такие как .play() или .pause(). Хотя использование метода .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. Вы только придерживаетесь этого кода и стиля:

  • меньше классов
  • без идентификаторов
  • использование this ключевого слова
  • поток условий
  • использование индексированных позиций
  • использование более подходящих jQuery методов
  • делегирование события
  • шаблон взаимной исключительности

Этот список можно продолжить, и подробности go по любому из этих пунктов позволяют избежать вопроса. Попробуйте демо, примените столько, сколько сможете - к своему собственному коду. Все детали прокомментированы в демоверсии. Удачи.

/*
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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...