如何检查添加的 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 对象。该术语称为取消引用。继续上面的例子:
括号表示法
$vid[0]
.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>
我有一个 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 对象。该术语称为取消引用。继续上面的例子:
括号表示法
$vid[0]
.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>