mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 01:39:24 +02:00
Update playlist for videojs 8
This commit is contained in:
parent
a36dff9849
commit
ed9048ec37
18 changed files with 19 additions and 3844 deletions
|
@ -1043,7 +1043,7 @@ class PlayListPlayer {
|
|||
$messagesFromPlayList[] = "videos_id={$video['videos_id']} empty playlist source ";
|
||||
continue;
|
||||
}
|
||||
$playListData[] = new PlayListElement($video['title'], $video['description'], @$video['duration'], $playListSources, $thumbnail, $images->poster, parseDurationToSeconds(@$externalOptions->videoStartSeconds), @$video['created'], @$video['likes'], @$video['views_count'], $video['videos_id']);
|
||||
$playListData[] = new PlayListElement(@$video['title'], @$video['description'], @$video['duration'], $playListSources, $thumbnail, $images->poster, parseDurationToSeconds(@$externalOptions->videoStartSeconds), @$video['created'], @$video['likes'], @$video['views_count'], $video['videos_id']);
|
||||
}
|
||||
return $playListData;
|
||||
}
|
||||
|
|
|
@ -132,10 +132,6 @@ if ($serie = PlayLists::isPlayListASerie($pl->getId())) {
|
|||
}
|
||||
$_REQUEST['hideAutoplaySwitch'] = 1;
|
||||
//var_dump($playListData_videos_id);exit;
|
||||
echo "<!-- line=".__LINE__." count=".count($playListData)." playlist_index={$playlist_index} playListData_videos_id=".count($playListData_videos_id)." getPlayListIndex()=".getPlayListIndex()." -->".PHP_EOL;
|
||||
foreach ($playListData_videos_id as $key => $value) {
|
||||
echo "<!-- line=".__LINE__." value[$key]=".$value." -->".PHP_EOL;
|
||||
}
|
||||
$pl_index = getPlayListIndex();
|
||||
$str = file_get_contents($global['systemRootPath'] . 'plugin/PlayLists/getStartPlayerJS.js');
|
||||
$str = str_replace('{$pl_index}', $pl_index, $str);
|
||||
|
@ -160,7 +156,7 @@ PlayerSkins::getStartPlayerJS($str);
|
|||
<link href="<?php echo getCDN(); ?>view/css/social.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="<?php echo getURL('node_modules/fontawesome-free/css/all.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<link href="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.css" rel="stylesheet">
|
||||
<link href="<?php echo getCDN(); ?>node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.css" rel="stylesheet">
|
||||
|
||||
<script src="<?php echo getURL('node_modules/jquery/dist/jquery.min.js'); ?>" type="text/javascript"></script>
|
||||
<?php
|
||||
|
@ -258,8 +254,8 @@ PlayerSkins::getStartPlayerJS($str);
|
|||
include $global['systemRootPath'] . 'view/include/video.min.js.php';
|
||||
?>
|
||||
<script src="<?php echo getURL('node_modules/jquery-ui-dist/jquery-ui.min.js'); ?>" type="text/javascript"></script>
|
||||
<script src="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.min.js"></script>
|
||||
<script src="<?php echo getURL('node_modules/moment/min/moment.min.js'); ?>"></script>
|
||||
<?php
|
||||
echo getTagIfExists('node_modules/moment/locale/' . getLanguage() . '.js');
|
||||
|
|
|
@ -29,7 +29,7 @@ $name = $plp->getName();
|
|||
<link href="<?php echo getURL('node_modules/video.js/dist/video-js.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
<link href="<?php echo getURL('view/css/social.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<link href="<?php echo getURL('plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.css'); ?>" rel="stylesheet">
|
||||
<link href="<?php echo getURL('node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.css'); ?>" rel="stylesheet">
|
||||
|
||||
<?php include $global['systemRootPath'] . 'view/include/head.php'; ?>
|
||||
<style>
|
||||
|
@ -140,10 +140,10 @@ $name = $plp->getName();
|
|||
echo AVideoPlugin::afterVideoJS();
|
||||
include $global['systemRootPath'] . 'view/include/footer.php';
|
||||
?>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('plugin/PlayLists/videojs-playlist/videojs-playlist.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('view/js/videojs-youtube/Youtube.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('node_modules/videojs-playlist/dist/videojs-playlist.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('view/js/videojs-youtube/Youtube.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script>
|
||||
|
||||
var playerPlaylist = <?php echo json_encode($playListData); ?>;
|
||||
|
|
|
@ -56,7 +56,7 @@ if (!empty($video['id'])) {
|
|||
<link href="<?php echo getURL('node_modules/video.js/dist/video-js.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
<link href="<?php echo getCDN(); ?>view/css/social.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<link href="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.css" rel="stylesheet">
|
||||
<link href="<?php echo getCDN(); ?>node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.css" rel="stylesheet">
|
||||
|
||||
<?php include $global['systemRootPath'] . 'view/include/head.php'; ?>
|
||||
<style>
|
||||
|
@ -204,8 +204,8 @@ if (!empty($video['id'])) {
|
|||
"view/js/BootstrapMenu.min.js");
|
||||
$jsURL = combineFiles($videoJSArray, "js");
|
||||
?>
|
||||
<script src="<?php echo $jsURL; ?>" type="text/javascript"></script><script src="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.js"></script>
|
||||
<script src="<?php echo $jsURL; ?>" type="text/javascript"></script><script src="<?php echo getCDN(); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.min.js"></script>
|
||||
<script src="<?php echo getCDN(); ?>view/js/videojs-youtube/Youtube.js"></script>
|
||||
<script>
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ if(empty($playListData)){
|
|||
<link href="<?php echo getURL('node_modules/video.js/dist/video-js.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
<link href="<?php echo getCDN(); ?>view/css/social.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<link href="<?php echo getCDN(); ?>plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.css" rel="stylesheet">
|
||||
<link href="<?php echo getCDN(); ?>node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.css" rel="stylesheet">
|
||||
|
||||
<?php include $global['systemRootPath'] . 'view/include/head.php'; ?>
|
||||
<style>
|
||||
|
@ -202,10 +202,10 @@ if(empty($playListData)){
|
|||
echo AVideoPlugin::afterVideoJS();
|
||||
include $global['systemRootPath'] . 'view/include/footer.php';
|
||||
?>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('plugin/PlayLists/videojs-playlist/videojs-playlist.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('plugin/PlayLists/videojs-playlist-ui/videojs-playlist-ui.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('view/js/videojs-youtube/Youtube.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('node_modules/videojs-playlist/dist/videojs-playlist.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('node_modules/videojs-playlist-ui/dist/videojs-playlist-ui.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script src="<?php echo getURL('view/js/videojs-youtube/Youtube.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script>
|
||||
|
||||
var playerPlaylist = <?php echo json_encode($playListData); ?>;
|
||||
|
|
|
@ -1,504 +0,0 @@
|
|||
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
|
||||
'use strict';
|
||||
|
||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
|
||||
var document = _interopDefault(require('global/document'));
|
||||
var videojs = _interopDefault(require('video.js'));
|
||||
|
||||
function _inheritsLoose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
subClass.__proto__ = superClass;
|
||||
}
|
||||
|
||||
var version = "3.5.2";
|
||||
|
||||
var dom = videojs.dom || videojs;
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
|
||||
|
||||
var indexOf = function indexOf(array, target) {
|
||||
for (var i = 0, length = array.length; i < length; i++) {
|
||||
if (array[i] === target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
|
||||
|
||||
|
||||
var supportsCssPointerEvents = function () {
|
||||
var element = document.createElement('x');
|
||||
element.style.cssText = 'pointer-events:auto';
|
||||
return element.style.pointerEvents === 'auto';
|
||||
}();
|
||||
|
||||
var defaults = {
|
||||
className: 'vjs-playlist',
|
||||
playOnSelect: false,
|
||||
supportsCssPointerEvents: supportsCssPointerEvents
|
||||
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
|
||||
// so it won't conflict with `vjs-icon-play
|
||||
// since it'll get added when we mouse out
|
||||
|
||||
var addSelectedClass = function addSelectedClass(el) {
|
||||
el.addClass('vjs-selected');
|
||||
};
|
||||
|
||||
var removeSelectedClass = function removeSelectedClass(el) {
|
||||
el.removeClass('vjs-selected');
|
||||
|
||||
if (el.thumbnail) {
|
||||
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
};
|
||||
|
||||
var upNext = function upNext(el) {
|
||||
el.addClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var notUpNext = function notUpNext(el) {
|
||||
el.removeClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var createThumbnail = function createThumbnail(thumbnail) {
|
||||
if (!thumbnail) {
|
||||
var placeholder = document.createElement('div');
|
||||
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
var picture = document.createElement('picture');
|
||||
picture.className = 'vjs-playlist-thumbnail';
|
||||
|
||||
if (typeof thumbnail === 'string') {
|
||||
// simple thumbnails
|
||||
var img = document.createElement('img');
|
||||
img.src = thumbnail;
|
||||
img.alt = '';
|
||||
picture.appendChild(img);
|
||||
} else {
|
||||
// responsive thumbnails
|
||||
// additional variations of a <picture> are specified as
|
||||
// <source> elements
|
||||
for (var i = 0; i < thumbnail.length - 1; i++) {
|
||||
var _variant = thumbnail[i];
|
||||
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
|
||||
|
||||
for (var prop in _variant) {
|
||||
source[prop] = _variant[prop];
|
||||
}
|
||||
|
||||
picture.appendChild(source);
|
||||
} // the default version of a <picture> is specified by an <img>
|
||||
|
||||
|
||||
var variant = thumbnail[thumbnail.length - 1];
|
||||
|
||||
var _img = document.createElement('img');
|
||||
|
||||
_img.alt = '';
|
||||
|
||||
for (var _prop in variant) {
|
||||
_img[_prop] = variant[_prop];
|
||||
}
|
||||
|
||||
picture.appendChild(_img);
|
||||
}
|
||||
|
||||
return picture;
|
||||
};
|
||||
|
||||
var Component = videojs.getComponent('Component');
|
||||
|
||||
var PlaylistMenuItem =
|
||||
/*#__PURE__*/
|
||||
function (_Component) {
|
||||
_inheritsLoose(PlaylistMenuItem, _Component);
|
||||
|
||||
function PlaylistMenuItem(player, playlistItem, settings) {
|
||||
var _this;
|
||||
|
||||
if (!playlistItem.item) {
|
||||
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
|
||||
}
|
||||
|
||||
_this = _Component.call(this, player, playlistItem) || this;
|
||||
_this.item = playlistItem.item;
|
||||
_this.playOnSelect = settings.playOnSelect;
|
||||
|
||||
_this.emitTapEvents();
|
||||
|
||||
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
|
||||
|
||||
_this.on('keydown', _this.handleKeyDown_);
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
var _proto = PlaylistMenuItem.prototype;
|
||||
|
||||
_proto.handleKeyDown_ = function handleKeyDown_(event) {
|
||||
// keycode 13 is <Enter>
|
||||
// keycode 32 is <Space>
|
||||
if (event.which === 13 || event.which === 32) {
|
||||
this.switchPlaylistItem_();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
|
||||
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
|
||||
|
||||
if (this.playOnSelect) {
|
||||
this.player_.play();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.createEl = function createEl() {
|
||||
var li = document.createElement('li');
|
||||
var item = this.options_.item;
|
||||
|
||||
if (typeof item.data === 'object') {
|
||||
var dataKeys = Object.keys(item.data);
|
||||
dataKeys.forEach(function (key) {
|
||||
var value = item.data[key];
|
||||
li.dataset[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
li.className = 'vjs-playlist-item';
|
||||
li.setAttribute('tabIndex', 0); // Thumbnail image
|
||||
|
||||
this.thumbnail = createThumbnail(item.thumbnail);
|
||||
li.appendChild(this.thumbnail); // Duration
|
||||
|
||||
if (item.duration) {
|
||||
var duration = document.createElement('time');
|
||||
var time = videojs.formatTime(item.duration);
|
||||
duration.className = 'vjs-playlist-duration';
|
||||
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
|
||||
duration.appendChild(document.createTextNode(time));
|
||||
li.appendChild(duration);
|
||||
} // Now playing
|
||||
|
||||
|
||||
var nowPlayingEl = document.createElement('span');
|
||||
var nowPlayingText = this.localize('Now Playing');
|
||||
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
|
||||
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
|
||||
nowPlayingEl.setAttribute('title', nowPlayingText);
|
||||
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
|
||||
|
||||
var titleContainerEl = document.createElement('div');
|
||||
titleContainerEl.className = 'vjs-playlist-title-container';
|
||||
this.thumbnail.appendChild(titleContainerEl); // Up next
|
||||
|
||||
var upNextEl = document.createElement('span');
|
||||
var upNextText = this.localize('Up Next');
|
||||
upNextEl.className = 'vjs-up-next-text';
|
||||
upNextEl.appendChild(document.createTextNode(upNextText));
|
||||
upNextEl.setAttribute('title', upNextText);
|
||||
titleContainerEl.appendChild(upNextEl); // Video title
|
||||
|
||||
var titleEl = document.createElement('cite');
|
||||
var titleText = item.name || this.localize('Untitled Video');
|
||||
titleEl.className = 'vjs-playlist-name';
|
||||
titleEl.appendChild(document.createTextNode(titleText));
|
||||
titleEl.setAttribute('title', titleText);
|
||||
titleContainerEl.appendChild(titleEl);
|
||||
return li;
|
||||
};
|
||||
|
||||
return PlaylistMenuItem;
|
||||
}(Component);
|
||||
|
||||
var PlaylistMenu =
|
||||
/*#__PURE__*/
|
||||
function (_Component2) {
|
||||
_inheritsLoose(PlaylistMenu, _Component2);
|
||||
|
||||
function PlaylistMenu(player, options) {
|
||||
var _this2;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist is required for the playlist component');
|
||||
}
|
||||
|
||||
_this2 = _Component2.call(this, player, options) || this;
|
||||
_this2.items = [];
|
||||
|
||||
if (options.horizontal) {
|
||||
_this2.addClass('vjs-playlist-horizontal');
|
||||
} else {
|
||||
_this2.addClass('vjs-playlist-vertical');
|
||||
} // If CSS pointer events aren't supported, we have to prevent
|
||||
// clicking on playlist items during ads with slightly more
|
||||
// invasive techniques. Details in the stylesheet.
|
||||
|
||||
|
||||
if (options.supportsCssPointerEvents) {
|
||||
_this2.addClass('vjs-csspointerevents');
|
||||
}
|
||||
|
||||
_this2.createPlaylist_();
|
||||
|
||||
if (!videojs.browser.TOUCH_ENABLED) {
|
||||
_this2.addClass('vjs-mouse');
|
||||
}
|
||||
|
||||
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
|
||||
_this2.update();
|
||||
}); // Keep track of whether an ad is playing so that the menu
|
||||
// appearance can be adapted appropriately
|
||||
|
||||
|
||||
_this2.on(player, 'adstart', function () {
|
||||
_this2.addClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on(player, 'adend', function () {
|
||||
_this2.removeClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on('dispose', function () {
|
||||
_this2.empty_();
|
||||
|
||||
player.playlistMenu = null;
|
||||
});
|
||||
|
||||
_this2.on(player, 'dispose', function () {
|
||||
_this2.dispose();
|
||||
});
|
||||
|
||||
return _this2;
|
||||
}
|
||||
|
||||
var _proto2 = PlaylistMenu.prototype;
|
||||
|
||||
_proto2.createEl = function createEl() {
|
||||
return dom.createEl('div', {
|
||||
className: this.options_.className
|
||||
});
|
||||
};
|
||||
|
||||
_proto2.empty_ = function empty_() {
|
||||
if (this.items && this.items.length) {
|
||||
this.items.forEach(function (i) {
|
||||
return i.dispose();
|
||||
});
|
||||
this.items.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.createPlaylist_ = function createPlaylist_() {
|
||||
var playlist = this.player_.playlist() || [];
|
||||
var list = this.el_.querySelector('.vjs-playlist-item-list');
|
||||
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
|
||||
|
||||
if (!list) {
|
||||
list = document.createElement('ol');
|
||||
list.className = 'vjs-playlist-item-list';
|
||||
this.el_.appendChild(list);
|
||||
}
|
||||
|
||||
this.empty_(); // create new items
|
||||
|
||||
for (var i = 0; i < playlist.length; i++) {
|
||||
var item = new PlaylistMenuItem(this.player_, {
|
||||
item: playlist[i]
|
||||
}, this.options_);
|
||||
this.items.push(item);
|
||||
list.appendChild(item.el_);
|
||||
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
|
||||
// none" so we use this element to block clicks during ad
|
||||
// playback.
|
||||
|
||||
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('li');
|
||||
overlay.className = 'vjs-playlist-ad-overlay';
|
||||
list.appendChild(overlay);
|
||||
} else {
|
||||
// Move overlay to end of list
|
||||
list.appendChild(overlay);
|
||||
} // select the current playlist item
|
||||
|
||||
|
||||
var selectedIndex = this.player_.playlist.currentItem();
|
||||
|
||||
if (this.items.length && selectedIndex >= 0) {
|
||||
addSelectedClass(this.items[selectedIndex]);
|
||||
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
|
||||
|
||||
if (thumbnail) {
|
||||
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.update = function update() {
|
||||
// replace the playlist items being displayed, if necessary
|
||||
var playlist = this.player_.playlist();
|
||||
|
||||
if (this.items.length !== playlist.length) {
|
||||
// if the menu is currently empty or the state is obviously out
|
||||
// of date, rebuild everything.
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
if (this.items[i].item !== playlist[i]) {
|
||||
// if any of the playlist items have changed, rebuild the
|
||||
// entire playlist
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
} // the playlist itself is unchanged so just update the selection
|
||||
|
||||
|
||||
var currentItem = this.player_.playlist.currentItem();
|
||||
|
||||
for (var _i = 0; _i < this.items.length; _i++) {
|
||||
var item = this.items[_i];
|
||||
|
||||
if (_i === currentItem) {
|
||||
addSelectedClass(item);
|
||||
|
||||
if (document.activeElement !== item.el()) {
|
||||
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
|
||||
notUpNext(item);
|
||||
} else if (_i === currentItem + 1) {
|
||||
removeSelectedClass(item);
|
||||
upNext(item);
|
||||
} else {
|
||||
removeSelectedClass(item);
|
||||
notUpNext(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return PlaylistMenu;
|
||||
}(Component);
|
||||
/**
|
||||
* Returns a boolean indicating whether an element has child elements.
|
||||
*
|
||||
* Note that this is distinct from whether it has child _nodes_.
|
||||
*
|
||||
* @param {HTMLElement} el
|
||||
* A DOM element.
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether the element has child elements.
|
||||
*/
|
||||
|
||||
|
||||
var hasChildEls = function hasChildEls(el) {
|
||||
for (var i = 0; i < el.childNodes.length; i++) {
|
||||
if (dom.isEl(el.childNodes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Finds the first empty root element.
|
||||
*
|
||||
* @param {string} className
|
||||
* An HTML class name to search for.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* A DOM element to use as the root for a playlist.
|
||||
*/
|
||||
|
||||
|
||||
var findRoot = function findRoot(className) {
|
||||
var all = document.querySelectorAll('.' + className);
|
||||
var el;
|
||||
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
if (!hasChildEls(all[i])) {
|
||||
el = all[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
/**
|
||||
* Initialize the plugin on a player.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*
|
||||
* @param {HTMLElement} [options.el]
|
||||
* A DOM element to use as a root node for the playlist.
|
||||
*
|
||||
* @param {string} [options.className]
|
||||
* An HTML class name to use to find a root node for the playlist.
|
||||
*
|
||||
* @param {boolean} [options.playOnSelect = false]
|
||||
* If true, will attempt to begin playback upon selecting a new
|
||||
* playlist item in the UI.
|
||||
*/
|
||||
|
||||
|
||||
var playlistUi = function playlistUi(options) {
|
||||
var player = this;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
|
||||
}
|
||||
|
||||
if (dom.isEl(options)) {
|
||||
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
|
||||
options = {
|
||||
el: options
|
||||
};
|
||||
}
|
||||
|
||||
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
|
||||
// PlaylistMenu, but retain the element and its location in the DOM because
|
||||
// it will be re-used.
|
||||
|
||||
if (player.playlistMenu) {
|
||||
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
|
||||
// element removed from the DOM.
|
||||
|
||||
if (el) {
|
||||
var parentNode = el.parentNode;
|
||||
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
|
||||
// empty it ourselves to be sure.
|
||||
|
||||
player.playlistMenu.dispose();
|
||||
dom.emptyEl(el); // Put the element back in its place.
|
||||
|
||||
if (nextSibling) {
|
||||
parentNode.insertBefore(el, nextSibling);
|
||||
} else {
|
||||
parentNode.appendChild(el);
|
||||
}
|
||||
|
||||
options.el = el;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dom.isEl(options.el)) {
|
||||
options.el = findRoot(options.className);
|
||||
}
|
||||
|
||||
player.playlistMenu = new PlaylistMenu(player, options);
|
||||
}; // register components
|
||||
|
||||
|
||||
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
|
||||
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
|
||||
|
||||
registerPlugin('playlistUi', playlistUi);
|
||||
playlistUi.VERSION = version;
|
||||
|
||||
module.exports = playlistUi;
|
|
@ -1 +0,0 @@
|
|||
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}
|
|
@ -1,500 +0,0 @@
|
|||
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
|
||||
import document from 'global/document';
|
||||
import videojs from 'video.js';
|
||||
|
||||
function _inheritsLoose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
subClass.__proto__ = superClass;
|
||||
}
|
||||
|
||||
var version = "3.5.2";
|
||||
|
||||
var dom = videojs.dom || videojs;
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
|
||||
|
||||
var indexOf = function indexOf(array, target) {
|
||||
for (var i = 0, length = array.length; i < length; i++) {
|
||||
if (array[i] === target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
|
||||
|
||||
|
||||
var supportsCssPointerEvents = function () {
|
||||
var element = document.createElement('x');
|
||||
element.style.cssText = 'pointer-events:auto';
|
||||
return element.style.pointerEvents === 'auto';
|
||||
}();
|
||||
|
||||
var defaults = {
|
||||
className: 'vjs-playlist',
|
||||
playOnSelect: false,
|
||||
supportsCssPointerEvents: supportsCssPointerEvents
|
||||
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
|
||||
// so it won't conflict with `vjs-icon-play
|
||||
// since it'll get added when we mouse out
|
||||
|
||||
var addSelectedClass = function addSelectedClass(el) {
|
||||
el.addClass('vjs-selected');
|
||||
};
|
||||
|
||||
var removeSelectedClass = function removeSelectedClass(el) {
|
||||
el.removeClass('vjs-selected');
|
||||
|
||||
if (el.thumbnail) {
|
||||
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
};
|
||||
|
||||
var upNext = function upNext(el) {
|
||||
el.addClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var notUpNext = function notUpNext(el) {
|
||||
el.removeClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var createThumbnail = function createThumbnail(thumbnail) {
|
||||
if (!thumbnail) {
|
||||
var placeholder = document.createElement('div');
|
||||
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
var picture = document.createElement('picture');
|
||||
picture.className = 'vjs-playlist-thumbnail';
|
||||
|
||||
if (typeof thumbnail === 'string') {
|
||||
// simple thumbnails
|
||||
var img = document.createElement('img');
|
||||
img.src = thumbnail;
|
||||
img.alt = '';
|
||||
picture.appendChild(img);
|
||||
} else {
|
||||
// responsive thumbnails
|
||||
// additional variations of a <picture> are specified as
|
||||
// <source> elements
|
||||
for (var i = 0; i < thumbnail.length - 1; i++) {
|
||||
var _variant = thumbnail[i];
|
||||
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
|
||||
|
||||
for (var prop in _variant) {
|
||||
source[prop] = _variant[prop];
|
||||
}
|
||||
|
||||
picture.appendChild(source);
|
||||
} // the default version of a <picture> is specified by an <img>
|
||||
|
||||
|
||||
var variant = thumbnail[thumbnail.length - 1];
|
||||
|
||||
var _img = document.createElement('img');
|
||||
|
||||
_img.alt = '';
|
||||
|
||||
for (var _prop in variant) {
|
||||
_img[_prop] = variant[_prop];
|
||||
}
|
||||
|
||||
picture.appendChild(_img);
|
||||
}
|
||||
|
||||
return picture;
|
||||
};
|
||||
|
||||
var Component = videojs.getComponent('Component');
|
||||
|
||||
var PlaylistMenuItem =
|
||||
/*#__PURE__*/
|
||||
function (_Component) {
|
||||
_inheritsLoose(PlaylistMenuItem, _Component);
|
||||
|
||||
function PlaylistMenuItem(player, playlistItem, settings) {
|
||||
var _this;
|
||||
|
||||
if (!playlistItem.item) {
|
||||
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
|
||||
}
|
||||
|
||||
_this = _Component.call(this, player, playlistItem) || this;
|
||||
_this.item = playlistItem.item;
|
||||
_this.playOnSelect = settings.playOnSelect;
|
||||
|
||||
_this.emitTapEvents();
|
||||
|
||||
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
|
||||
|
||||
_this.on('keydown', _this.handleKeyDown_);
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
var _proto = PlaylistMenuItem.prototype;
|
||||
|
||||
_proto.handleKeyDown_ = function handleKeyDown_(event) {
|
||||
// keycode 13 is <Enter>
|
||||
// keycode 32 is <Space>
|
||||
if (event.which === 13 || event.which === 32) {
|
||||
this.switchPlaylistItem_();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
|
||||
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
|
||||
|
||||
if (this.playOnSelect) {
|
||||
this.player_.play();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.createEl = function createEl() {
|
||||
var li = document.createElement('li');
|
||||
var item = this.options_.item;
|
||||
|
||||
if (typeof item.data === 'object') {
|
||||
var dataKeys = Object.keys(item.data);
|
||||
dataKeys.forEach(function (key) {
|
||||
var value = item.data[key];
|
||||
li.dataset[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
li.className = 'vjs-playlist-item';
|
||||
li.setAttribute('tabIndex', 0); // Thumbnail image
|
||||
|
||||
this.thumbnail = createThumbnail(item.thumbnail);
|
||||
li.appendChild(this.thumbnail); // Duration
|
||||
|
||||
if (item.duration) {
|
||||
var duration = document.createElement('time');
|
||||
var time = videojs.formatTime(item.duration);
|
||||
duration.className = 'vjs-playlist-duration';
|
||||
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
|
||||
duration.appendChild(document.createTextNode(time));
|
||||
li.appendChild(duration);
|
||||
} // Now playing
|
||||
|
||||
|
||||
var nowPlayingEl = document.createElement('span');
|
||||
var nowPlayingText = this.localize('Now Playing');
|
||||
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
|
||||
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
|
||||
nowPlayingEl.setAttribute('title', nowPlayingText);
|
||||
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
|
||||
|
||||
var titleContainerEl = document.createElement('div');
|
||||
titleContainerEl.className = 'vjs-playlist-title-container';
|
||||
this.thumbnail.appendChild(titleContainerEl); // Up next
|
||||
|
||||
var upNextEl = document.createElement('span');
|
||||
var upNextText = this.localize('Up Next');
|
||||
upNextEl.className = 'vjs-up-next-text';
|
||||
upNextEl.appendChild(document.createTextNode(upNextText));
|
||||
upNextEl.setAttribute('title', upNextText);
|
||||
titleContainerEl.appendChild(upNextEl); // Video title
|
||||
|
||||
var titleEl = document.createElement('cite');
|
||||
var titleText = item.name || this.localize('Untitled Video');
|
||||
titleEl.className = 'vjs-playlist-name';
|
||||
titleEl.appendChild(document.createTextNode(titleText));
|
||||
titleEl.setAttribute('title', titleText);
|
||||
titleContainerEl.appendChild(titleEl);
|
||||
return li;
|
||||
};
|
||||
|
||||
return PlaylistMenuItem;
|
||||
}(Component);
|
||||
|
||||
var PlaylistMenu =
|
||||
/*#__PURE__*/
|
||||
function (_Component2) {
|
||||
_inheritsLoose(PlaylistMenu, _Component2);
|
||||
|
||||
function PlaylistMenu(player, options) {
|
||||
var _this2;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist is required for the playlist component');
|
||||
}
|
||||
|
||||
_this2 = _Component2.call(this, player, options) || this;
|
||||
_this2.items = [];
|
||||
|
||||
if (options.horizontal) {
|
||||
_this2.addClass('vjs-playlist-horizontal');
|
||||
} else {
|
||||
_this2.addClass('vjs-playlist-vertical');
|
||||
} // If CSS pointer events aren't supported, we have to prevent
|
||||
// clicking on playlist items during ads with slightly more
|
||||
// invasive techniques. Details in the stylesheet.
|
||||
|
||||
|
||||
if (options.supportsCssPointerEvents) {
|
||||
_this2.addClass('vjs-csspointerevents');
|
||||
}
|
||||
|
||||
_this2.createPlaylist_();
|
||||
|
||||
if (!videojs.browser.TOUCH_ENABLED) {
|
||||
_this2.addClass('vjs-mouse');
|
||||
}
|
||||
|
||||
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
|
||||
_this2.update();
|
||||
}); // Keep track of whether an ad is playing so that the menu
|
||||
// appearance can be adapted appropriately
|
||||
|
||||
|
||||
_this2.on(player, 'adstart', function () {
|
||||
_this2.addClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on(player, 'adend', function () {
|
||||
_this2.removeClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on('dispose', function () {
|
||||
_this2.empty_();
|
||||
|
||||
player.playlistMenu = null;
|
||||
});
|
||||
|
||||
_this2.on(player, 'dispose', function () {
|
||||
_this2.dispose();
|
||||
});
|
||||
|
||||
return _this2;
|
||||
}
|
||||
|
||||
var _proto2 = PlaylistMenu.prototype;
|
||||
|
||||
_proto2.createEl = function createEl() {
|
||||
return dom.createEl('div', {
|
||||
className: this.options_.className
|
||||
});
|
||||
};
|
||||
|
||||
_proto2.empty_ = function empty_() {
|
||||
if (this.items && this.items.length) {
|
||||
this.items.forEach(function (i) {
|
||||
return i.dispose();
|
||||
});
|
||||
this.items.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.createPlaylist_ = function createPlaylist_() {
|
||||
var playlist = this.player_.playlist() || [];
|
||||
var list = this.el_.querySelector('.vjs-playlist-item-list');
|
||||
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
|
||||
|
||||
if (!list) {
|
||||
list = document.createElement('ol');
|
||||
list.className = 'vjs-playlist-item-list';
|
||||
this.el_.appendChild(list);
|
||||
}
|
||||
|
||||
this.empty_(); // create new items
|
||||
|
||||
for (var i = 0; i < playlist.length; i++) {
|
||||
var item = new PlaylistMenuItem(this.player_, {
|
||||
item: playlist[i]
|
||||
}, this.options_);
|
||||
this.items.push(item);
|
||||
list.appendChild(item.el_);
|
||||
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
|
||||
// none" so we use this element to block clicks during ad
|
||||
// playback.
|
||||
|
||||
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('li');
|
||||
overlay.className = 'vjs-playlist-ad-overlay';
|
||||
list.appendChild(overlay);
|
||||
} else {
|
||||
// Move overlay to end of list
|
||||
list.appendChild(overlay);
|
||||
} // select the current playlist item
|
||||
|
||||
|
||||
var selectedIndex = this.player_.playlist.currentItem();
|
||||
|
||||
if (this.items.length && selectedIndex >= 0) {
|
||||
addSelectedClass(this.items[selectedIndex]);
|
||||
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
|
||||
|
||||
if (thumbnail) {
|
||||
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.update = function update() {
|
||||
// replace the playlist items being displayed, if necessary
|
||||
var playlist = this.player_.playlist();
|
||||
|
||||
if (this.items.length !== playlist.length) {
|
||||
// if the menu is currently empty or the state is obviously out
|
||||
// of date, rebuild everything.
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
if (this.items[i].item !== playlist[i]) {
|
||||
// if any of the playlist items have changed, rebuild the
|
||||
// entire playlist
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
} // the playlist itself is unchanged so just update the selection
|
||||
|
||||
|
||||
var currentItem = this.player_.playlist.currentItem();
|
||||
|
||||
for (var _i = 0; _i < this.items.length; _i++) {
|
||||
var item = this.items[_i];
|
||||
|
||||
if (_i === currentItem) {
|
||||
addSelectedClass(item);
|
||||
|
||||
if (document.activeElement !== item.el()) {
|
||||
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
|
||||
notUpNext(item);
|
||||
} else if (_i === currentItem + 1) {
|
||||
removeSelectedClass(item);
|
||||
upNext(item);
|
||||
} else {
|
||||
removeSelectedClass(item);
|
||||
notUpNext(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return PlaylistMenu;
|
||||
}(Component);
|
||||
/**
|
||||
* Returns a boolean indicating whether an element has child elements.
|
||||
*
|
||||
* Note that this is distinct from whether it has child _nodes_.
|
||||
*
|
||||
* @param {HTMLElement} el
|
||||
* A DOM element.
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether the element has child elements.
|
||||
*/
|
||||
|
||||
|
||||
var hasChildEls = function hasChildEls(el) {
|
||||
for (var i = 0; i < el.childNodes.length; i++) {
|
||||
if (dom.isEl(el.childNodes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Finds the first empty root element.
|
||||
*
|
||||
* @param {string} className
|
||||
* An HTML class name to search for.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* A DOM element to use as the root for a playlist.
|
||||
*/
|
||||
|
||||
|
||||
var findRoot = function findRoot(className) {
|
||||
var all = document.querySelectorAll('.' + className);
|
||||
var el;
|
||||
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
if (!hasChildEls(all[i])) {
|
||||
el = all[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
/**
|
||||
* Initialize the plugin on a player.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*
|
||||
* @param {HTMLElement} [options.el]
|
||||
* A DOM element to use as a root node for the playlist.
|
||||
*
|
||||
* @param {string} [options.className]
|
||||
* An HTML class name to use to find a root node for the playlist.
|
||||
*
|
||||
* @param {boolean} [options.playOnSelect = false]
|
||||
* If true, will attempt to begin playback upon selecting a new
|
||||
* playlist item in the UI.
|
||||
*/
|
||||
|
||||
|
||||
var playlistUi = function playlistUi(options) {
|
||||
var player = this;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
|
||||
}
|
||||
|
||||
if (dom.isEl(options)) {
|
||||
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
|
||||
options = {
|
||||
el: options
|
||||
};
|
||||
}
|
||||
|
||||
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
|
||||
// PlaylistMenu, but retain the element and its location in the DOM because
|
||||
// it will be re-used.
|
||||
|
||||
if (player.playlistMenu) {
|
||||
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
|
||||
// element removed from the DOM.
|
||||
|
||||
if (el) {
|
||||
var parentNode = el.parentNode;
|
||||
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
|
||||
// empty it ourselves to be sure.
|
||||
|
||||
player.playlistMenu.dispose();
|
||||
dom.emptyEl(el); // Put the element back in its place.
|
||||
|
||||
if (nextSibling) {
|
||||
parentNode.insertBefore(el, nextSibling);
|
||||
} else {
|
||||
parentNode.appendChild(el);
|
||||
}
|
||||
|
||||
options.el = el;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dom.isEl(options.el)) {
|
||||
options.el = findRoot(options.className);
|
||||
}
|
||||
|
||||
player.playlistMenu = new PlaylistMenu(player, options);
|
||||
}; // register components
|
||||
|
||||
|
||||
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
|
||||
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
|
||||
|
||||
registerPlugin('playlistUi', playlistUi);
|
||||
playlistUi.VERSION = version;
|
||||
|
||||
export default playlistUi;
|
|
@ -1,509 +0,0 @@
|
|||
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/document'), require('video.js')) :
|
||||
typeof define === 'function' && define.amd ? define(['global/document', 'video.js'], factory) :
|
||||
(global.videojsPlaylistUi = factory(global.document,global.videojs));
|
||||
}(this, (function (document,videojs) { 'use strict';
|
||||
|
||||
document = document && document.hasOwnProperty('default') ? document['default'] : document;
|
||||
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
|
||||
|
||||
function _inheritsLoose(subClass, superClass) {
|
||||
subClass.prototype = Object.create(superClass.prototype);
|
||||
subClass.prototype.constructor = subClass;
|
||||
subClass.__proto__ = superClass;
|
||||
}
|
||||
|
||||
var version = "3.5.2";
|
||||
|
||||
var dom = videojs.dom || videojs;
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
|
||||
|
||||
var indexOf = function indexOf(array, target) {
|
||||
for (var i = 0, length = array.length; i < length; i++) {
|
||||
if (array[i] === target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
|
||||
|
||||
|
||||
var supportsCssPointerEvents = function () {
|
||||
var element = document.createElement('x');
|
||||
element.style.cssText = 'pointer-events:auto';
|
||||
return element.style.pointerEvents === 'auto';
|
||||
}();
|
||||
|
||||
var defaults = {
|
||||
className: 'vjs-playlist',
|
||||
playOnSelect: false,
|
||||
supportsCssPointerEvents: supportsCssPointerEvents
|
||||
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
|
||||
// so it won't conflict with `vjs-icon-play
|
||||
// since it'll get added when we mouse out
|
||||
|
||||
var addSelectedClass = function addSelectedClass(el) {
|
||||
el.addClass('vjs-selected');
|
||||
};
|
||||
|
||||
var removeSelectedClass = function removeSelectedClass(el) {
|
||||
el.removeClass('vjs-selected');
|
||||
|
||||
if (el.thumbnail) {
|
||||
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
};
|
||||
|
||||
var upNext = function upNext(el) {
|
||||
el.addClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var notUpNext = function notUpNext(el) {
|
||||
el.removeClass('vjs-up-next');
|
||||
};
|
||||
|
||||
var createThumbnail = function createThumbnail(thumbnail) {
|
||||
if (!thumbnail) {
|
||||
var placeholder = document.createElement('div');
|
||||
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
var picture = document.createElement('picture');
|
||||
picture.className = 'vjs-playlist-thumbnail';
|
||||
|
||||
if (typeof thumbnail === 'string') {
|
||||
// simple thumbnails
|
||||
var img = document.createElement('img');
|
||||
img.src = thumbnail;
|
||||
img.alt = '';
|
||||
picture.appendChild(img);
|
||||
} else {
|
||||
// responsive thumbnails
|
||||
// additional variations of a <picture> are specified as
|
||||
// <source> elements
|
||||
for (var i = 0; i < thumbnail.length - 1; i++) {
|
||||
var _variant = thumbnail[i];
|
||||
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
|
||||
|
||||
for (var prop in _variant) {
|
||||
source[prop] = _variant[prop];
|
||||
}
|
||||
|
||||
picture.appendChild(source);
|
||||
} // the default version of a <picture> is specified by an <img>
|
||||
|
||||
|
||||
var variant = thumbnail[thumbnail.length - 1];
|
||||
|
||||
var _img = document.createElement('img');
|
||||
|
||||
_img.alt = '';
|
||||
|
||||
for (var _prop in variant) {
|
||||
_img[_prop] = variant[_prop];
|
||||
}
|
||||
|
||||
picture.appendChild(_img);
|
||||
}
|
||||
|
||||
return picture;
|
||||
};
|
||||
|
||||
var Component = videojs.getComponent('Component');
|
||||
|
||||
var PlaylistMenuItem =
|
||||
/*#__PURE__*/
|
||||
function (_Component) {
|
||||
_inheritsLoose(PlaylistMenuItem, _Component);
|
||||
|
||||
function PlaylistMenuItem(player, playlistItem, settings) {
|
||||
var _this;
|
||||
|
||||
if (!playlistItem.item) {
|
||||
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
|
||||
}
|
||||
|
||||
_this = _Component.call(this, player, playlistItem) || this;
|
||||
_this.item = playlistItem.item;
|
||||
_this.playOnSelect = settings.playOnSelect;
|
||||
|
||||
_this.emitTapEvents();
|
||||
|
||||
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
|
||||
|
||||
_this.on('keydown', _this.handleKeyDown_);
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
var _proto = PlaylistMenuItem.prototype;
|
||||
|
||||
_proto.handleKeyDown_ = function handleKeyDown_(event) {
|
||||
// keycode 13 is <Enter>
|
||||
// keycode 32 is <Space>
|
||||
if (event.which === 13 || event.which === 32) {
|
||||
this.switchPlaylistItem_();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
|
||||
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
|
||||
|
||||
if (this.playOnSelect) {
|
||||
this.player_.play();
|
||||
}
|
||||
};
|
||||
|
||||
_proto.createEl = function createEl() {
|
||||
var li = document.createElement('li');
|
||||
var item = this.options_.item;
|
||||
|
||||
if (typeof item.data === 'object') {
|
||||
var dataKeys = Object.keys(item.data);
|
||||
dataKeys.forEach(function (key) {
|
||||
var value = item.data[key];
|
||||
li.dataset[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
/* AVideo add classname on item */
|
||||
li.className = 'vjs-playlist-item '+item.className;
|
||||
li.setAttribute('tabIndex', 0); // Thumbnail image
|
||||
|
||||
this.thumbnail = createThumbnail(item.thumbnail);
|
||||
li.appendChild(this.thumbnail); // Duration
|
||||
|
||||
if (item.duration) {
|
||||
var duration = document.createElement('time');
|
||||
var time = videojs.formatTime(item.duration);
|
||||
duration.className = 'vjs-playlist-duration';
|
||||
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
|
||||
duration.appendChild(document.createTextNode(time));
|
||||
li.appendChild(duration);
|
||||
} // Now playing
|
||||
|
||||
|
||||
var nowPlayingEl = document.createElement('span');
|
||||
var nowPlayingText = this.localize('Now Playing');
|
||||
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
|
||||
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
|
||||
nowPlayingEl.setAttribute('title', nowPlayingText);
|
||||
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
|
||||
|
||||
var titleContainerEl = document.createElement('div');
|
||||
titleContainerEl.className = 'vjs-playlist-title-container';
|
||||
this.thumbnail.appendChild(titleContainerEl); // Up next
|
||||
|
||||
var upNextEl = document.createElement('span');
|
||||
var upNextText = this.localize('Up Next');
|
||||
upNextEl.className = 'vjs-up-next-text';
|
||||
upNextEl.appendChild(document.createTextNode(upNextText));
|
||||
upNextEl.setAttribute('title', upNextText);
|
||||
titleContainerEl.appendChild(upNextEl); // Video title
|
||||
|
||||
var titleEl = document.createElement('cite');
|
||||
var titleText = item.name || this.localize('Untitled Video');
|
||||
titleEl.className = 'vjs-playlist-name';
|
||||
titleEl.appendChild(document.createTextNode(titleText));
|
||||
titleEl.setAttribute('title', titleText);
|
||||
titleContainerEl.appendChild(titleEl);
|
||||
return li;
|
||||
};
|
||||
|
||||
return PlaylistMenuItem;
|
||||
}(Component);
|
||||
|
||||
var PlaylistMenu =
|
||||
/*#__PURE__*/
|
||||
function (_Component2) {
|
||||
_inheritsLoose(PlaylistMenu, _Component2);
|
||||
|
||||
function PlaylistMenu(player, options) {
|
||||
var _this2;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist is required for the playlist component');
|
||||
}
|
||||
|
||||
_this2 = _Component2.call(this, player, options) || this;
|
||||
_this2.items = [];
|
||||
|
||||
if (options.horizontal) {
|
||||
_this2.addClass('vjs-playlist-horizontal');
|
||||
} else {
|
||||
_this2.addClass('vjs-playlist-vertical');
|
||||
} // If CSS pointer events aren't supported, we have to prevent
|
||||
// clicking on playlist items during ads with slightly more
|
||||
// invasive techniques. Details in the stylesheet.
|
||||
|
||||
|
||||
if (options.supportsCssPointerEvents) {
|
||||
_this2.addClass('vjs-csspointerevents');
|
||||
}
|
||||
|
||||
_this2.createPlaylist_();
|
||||
|
||||
if (!videojs.browser.TOUCH_ENABLED) {
|
||||
_this2.addClass('vjs-mouse');
|
||||
}
|
||||
|
||||
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
|
||||
_this2.update();
|
||||
}); // Keep track of whether an ad is playing so that the menu
|
||||
// appearance can be adapted appropriately
|
||||
|
||||
|
||||
_this2.on(player, 'adstart', function () {
|
||||
_this2.addClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on(player, 'adend', function () {
|
||||
_this2.removeClass('vjs-ad-playing');
|
||||
});
|
||||
|
||||
_this2.on('dispose', function () {
|
||||
_this2.empty_();
|
||||
|
||||
player.playlistMenu = null;
|
||||
});
|
||||
|
||||
_this2.on(player, 'dispose', function () {
|
||||
_this2.dispose();
|
||||
});
|
||||
|
||||
return _this2;
|
||||
}
|
||||
|
||||
var _proto2 = PlaylistMenu.prototype;
|
||||
|
||||
_proto2.createEl = function createEl() {
|
||||
return dom.createEl('div', {
|
||||
className: this.options_.className
|
||||
});
|
||||
};
|
||||
|
||||
_proto2.empty_ = function empty_() {
|
||||
if (this.items && this.items.length) {
|
||||
this.items.forEach(function (i) {
|
||||
return i.dispose();
|
||||
});
|
||||
this.items.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.createPlaylist_ = function createPlaylist_() {
|
||||
var playlist = this.player_.playlist() || [];
|
||||
var list = this.el_.querySelector('.vjs-playlist-item-list');
|
||||
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
|
||||
|
||||
if (!list) {
|
||||
list = document.createElement('ol');
|
||||
list.className = 'vjs-playlist-item-list';
|
||||
this.el_.appendChild(list);
|
||||
}
|
||||
|
||||
this.empty_(); // create new items
|
||||
|
||||
for (var i = 0; i < playlist.length; i++) {
|
||||
var item = new PlaylistMenuItem(this.player_, {
|
||||
item: playlist[i]
|
||||
}, this.options_);
|
||||
this.items.push(item);
|
||||
list.appendChild(item.el_);
|
||||
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
|
||||
// none" so we use this element to block clicks during ad
|
||||
// playback.
|
||||
|
||||
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('li');
|
||||
overlay.className = 'vjs-playlist-ad-overlay';
|
||||
list.appendChild(overlay);
|
||||
} else {
|
||||
// Move overlay to end of list
|
||||
list.appendChild(overlay);
|
||||
} // select the current playlist item
|
||||
|
||||
|
||||
var selectedIndex = this.player_.playlist.currentItem();
|
||||
|
||||
if (this.items.length && selectedIndex >= 0) {
|
||||
addSelectedClass(this.items[selectedIndex]);
|
||||
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
|
||||
|
||||
if (thumbnail) {
|
||||
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_proto2.update = function update() {
|
||||
// replace the playlist items being displayed, if necessary
|
||||
var playlist = this.player_.playlist();
|
||||
|
||||
if (this.items.length !== playlist.length) {
|
||||
// if the menu is currently empty or the state is obviously out
|
||||
// of date, rebuild everything.
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
if (this.items[i].item !== playlist[i]) {
|
||||
// if any of the playlist items have changed, rebuild the
|
||||
// entire playlist
|
||||
this.createPlaylist_();
|
||||
return;
|
||||
}
|
||||
} // the playlist itself is unchanged so just update the selection
|
||||
|
||||
|
||||
var currentItem = this.player_.playlist.currentItem();
|
||||
|
||||
for (var _i = 0; _i < this.items.length; _i++) {
|
||||
var item = this.items[_i];
|
||||
|
||||
if (_i === currentItem) {
|
||||
addSelectedClass(item);
|
||||
|
||||
if (document.activeElement !== item.el()) {
|
||||
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
|
||||
}
|
||||
|
||||
notUpNext(item);
|
||||
} else if (_i === currentItem + 1) {
|
||||
removeSelectedClass(item);
|
||||
upNext(item);
|
||||
} else {
|
||||
removeSelectedClass(item);
|
||||
notUpNext(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return PlaylistMenu;
|
||||
}(Component);
|
||||
/**
|
||||
* Returns a boolean indicating whether an element has child elements.
|
||||
*
|
||||
* Note that this is distinct from whether it has child _nodes_.
|
||||
*
|
||||
* @param {HTMLElement} el
|
||||
* A DOM element.
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether the element has child elements.
|
||||
*/
|
||||
|
||||
|
||||
var hasChildEls = function hasChildEls(el) {
|
||||
for (var i = 0; i < el.childNodes.length; i++) {
|
||||
if (dom.isEl(el.childNodes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Finds the first empty root element.
|
||||
*
|
||||
* @param {string} className
|
||||
* An HTML class name to search for.
|
||||
*
|
||||
* @return {HTMLElement}
|
||||
* A DOM element to use as the root for a playlist.
|
||||
*/
|
||||
|
||||
|
||||
var findRoot = function findRoot(className) {
|
||||
var all = document.querySelectorAll('.' + className);
|
||||
var el;
|
||||
|
||||
for (var i = 0; i < all.length; i++) {
|
||||
if (!hasChildEls(all[i])) {
|
||||
el = all[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
/**
|
||||
* Initialize the plugin on a player.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* An options object.
|
||||
*
|
||||
* @param {HTMLElement} [options.el]
|
||||
* A DOM element to use as a root node for the playlist.
|
||||
*
|
||||
* @param {string} [options.className]
|
||||
* An HTML class name to use to find a root node for the playlist.
|
||||
*
|
||||
* @param {boolean} [options.playOnSelect = false]
|
||||
* If true, will attempt to begin playback upon selecting a new
|
||||
* playlist item in the UI.
|
||||
*/
|
||||
|
||||
|
||||
var playlistUi = function playlistUi(options) {
|
||||
var player = this;
|
||||
|
||||
if (!player.playlist) {
|
||||
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
|
||||
}
|
||||
|
||||
if (dom.isEl(options)) {
|
||||
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
|
||||
options = {
|
||||
el: options
|
||||
};
|
||||
}
|
||||
|
||||
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
|
||||
// PlaylistMenu, but retain the element and its location in the DOM because
|
||||
// it will be re-used.
|
||||
|
||||
if (player.playlistMenu) {
|
||||
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
|
||||
// element removed from the DOM.
|
||||
|
||||
if (el) {
|
||||
var parentNode = el.parentNode;
|
||||
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
|
||||
// empty it ourselves to be sure.
|
||||
|
||||
player.playlistMenu.dispose();
|
||||
dom.emptyEl(el); // Put the element back in its place.
|
||||
|
||||
if (nextSibling) {
|
||||
parentNode.insertBefore(el, nextSibling);
|
||||
} else {
|
||||
parentNode.appendChild(el);
|
||||
}
|
||||
|
||||
options.el = el;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dom.isEl(options.el)) {
|
||||
options.el = findRoot(options.className);
|
||||
}
|
||||
|
||||
player.playlistMenu = new PlaylistMenu(player, options);
|
||||
}; // register components
|
||||
|
||||
|
||||
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
|
||||
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
|
||||
|
||||
registerPlugin('playlistUi', playlistUi);
|
||||
playlistUi.VERSION = version;
|
||||
|
||||
return playlistUi;
|
||||
|
||||
})));
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}
|
|
@ -1 +0,0 @@
|
|||
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}
|
|
@ -1,767 +0,0 @@
|
|||
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
|
||||
'use strict';
|
||||
|
||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
|
||||
var videojs = _interopDefault(require('video.js'));
|
||||
|
||||
/**
|
||||
* Validates a number of seconds to use as the auto-advance delay.
|
||||
*
|
||||
* @private
|
||||
* @param {number} s
|
||||
* The number to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether this is a valid second or not
|
||||
*/
|
||||
var validSeconds = function validSeconds(s) {
|
||||
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
|
||||
};
|
||||
/**
|
||||
* Resets the auto-advance behavior of a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to reset the behavior on
|
||||
*/
|
||||
|
||||
|
||||
var reset = function reset(player) {
|
||||
var aa = player.playlist.autoadvance_;
|
||||
|
||||
if (aa.timeout) {
|
||||
player.clearTimeout(aa.timeout);
|
||||
}
|
||||
|
||||
if (aa.trigger) {
|
||||
player.off('ended', aa.trigger);
|
||||
}
|
||||
|
||||
aa.timeout = null;
|
||||
aa.trigger = null;
|
||||
};
|
||||
/**
|
||||
* Sets up auto-advance behavior on a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* the current player
|
||||
*
|
||||
* @param {number} delay
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*
|
||||
* @return {undefined}
|
||||
* Used to short circuit function logic
|
||||
*/
|
||||
|
||||
|
||||
var setup = function setup(player, delay) {
|
||||
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
|
||||
// called with a valid value.
|
||||
|
||||
if (!validSeconds(delay)) {
|
||||
player.playlist.autoadvance_.delay = null;
|
||||
return;
|
||||
}
|
||||
|
||||
player.playlist.autoadvance_.delay = delay;
|
||||
|
||||
player.playlist.autoadvance_.trigger = function () {
|
||||
// This calls setup again, which will reset the existing auto-advance and
|
||||
// set up another auto-advance for the next "ended" event.
|
||||
var cancelOnPlay = function cancelOnPlay() {
|
||||
return setup(player, delay);
|
||||
}; // If there is a "play" event while we're waiting for an auto-advance,
|
||||
// we need to cancel the auto-advance. This could mean the user seeked
|
||||
// back into the content or restarted the content. This is reproducible
|
||||
// with an auto-advance > 0.
|
||||
|
||||
|
||||
player.one('play', cancelOnPlay);
|
||||
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
|
||||
reset(player);
|
||||
player.off('play', cancelOnPlay);
|
||||
player.playlist.next();
|
||||
}, delay * 1000);
|
||||
};
|
||||
|
||||
player.one('ended', player.playlist.autoadvance_.trigger);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all remote text tracks from a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to clear tracks on
|
||||
*/
|
||||
|
||||
var clearTracks = function clearTracks(player) {
|
||||
var tracks = player.remoteTextTracks();
|
||||
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
|
||||
// `TextTrackList` object is a live DOM list (not an array).
|
||||
|
||||
while (i--) {
|
||||
player.removeRemoteTextTrack(tracks[i]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays an item on a player's playlist.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to play the item on
|
||||
*
|
||||
* @param {Object} item
|
||||
* A source from the playlist.
|
||||
*
|
||||
* @return {Player}
|
||||
* The player that is now playing the item
|
||||
*/
|
||||
|
||||
|
||||
var playItem = function playItem(player, item) {
|
||||
var replay = !player.paused() || player.ended();
|
||||
player.trigger('beforeplaylistitem', item);
|
||||
player.poster(item.poster || '');
|
||||
player.src(item.sources);
|
||||
clearTracks(player);
|
||||
player.ready(function () {
|
||||
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
|
||||
player.trigger('playlistitem', item);
|
||||
|
||||
if (replay) {
|
||||
var playPromise = player.play(); // silence error when a pause interrupts a play request
|
||||
// on browsers which return a promise
|
||||
|
||||
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
|
||||
playPromise.then(null, function (e) {});
|
||||
}
|
||||
}
|
||||
|
||||
setup(player, player.playlist.autoadvance_.delay);
|
||||
});
|
||||
return player;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given two sources, check to see whether the two sources are equal.
|
||||
* If both source urls have a protocol, the protocols must match, otherwise, protocols
|
||||
* are ignored.
|
||||
*
|
||||
* @private
|
||||
* @param {string|Object} source1
|
||||
* The first source
|
||||
*
|
||||
* @param {string|Object} source2
|
||||
* The second source
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
var sourceEquals = function sourceEquals(source1, source2) {
|
||||
var src1 = source1;
|
||||
var src2 = source2;
|
||||
|
||||
if (typeof source1 === 'object') {
|
||||
src1 = source1.src;
|
||||
}
|
||||
|
||||
if (typeof source2 === 'object') {
|
||||
src2 = source2.src;
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src1)) {
|
||||
src2 = src2.slice(src2.indexOf('//'));
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src2)) {
|
||||
src1 = src1.slice(src1.indexOf('//'));
|
||||
}
|
||||
|
||||
return src1 === src2;
|
||||
};
|
||||
/**
|
||||
* Look through an array of playlist items for a specific `source`;
|
||||
* checking both the value of elements and the value of their `src`
|
||||
* property.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array of playlist items to look through
|
||||
*
|
||||
* @param {string} src
|
||||
* The source to look for
|
||||
*
|
||||
* @return {number}
|
||||
* The index of that source or -1
|
||||
*/
|
||||
|
||||
|
||||
var indexInSources = function indexInSources(arr, src) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var sources = arr[i].sources;
|
||||
|
||||
if (Array.isArray(sources)) {
|
||||
for (var j = 0; j < sources.length; j++) {
|
||||
var source = sources[j];
|
||||
|
||||
if (source && sourceEquals(source, src)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Randomize the contents of an array.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array.
|
||||
*
|
||||
* @return {Array}
|
||||
* The same array that was passed in.
|
||||
*/
|
||||
|
||||
|
||||
var randomize = function randomize(arr) {
|
||||
var index = -1;
|
||||
var lastIndex = arr.length - 1;
|
||||
|
||||
while (++index < arr.length) {
|
||||
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
|
||||
var value = arr[rand];
|
||||
arr[rand] = arr[index];
|
||||
arr[index] = value;
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
/**
|
||||
* Factory function for creating new playlist implementation on the given player.
|
||||
*
|
||||
* API summary:
|
||||
*
|
||||
* playlist(['a', 'b', 'c']) // setter
|
||||
* playlist() // getter
|
||||
* playlist.currentItem() // getter, 0
|
||||
* playlist.currentItem(1) // setter, 1
|
||||
* playlist.next() // 'c'
|
||||
* playlist.previous() // 'b'
|
||||
* playlist.first() // 'a'
|
||||
* playlist.last() // 'c'
|
||||
* playlist.autoadvance(5) // 5 second delay
|
||||
* playlist.autoadvance() // cancel autoadvance
|
||||
*
|
||||
* @param {Player} player
|
||||
* The current player
|
||||
*
|
||||
* @param {Array=} initialList
|
||||
* If given, an initial list of sources with which to populate
|
||||
* the playlist.
|
||||
*
|
||||
* @param {number=} initialIndex
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Function}
|
||||
* Returns the playlist function specific to the given player.
|
||||
*/
|
||||
|
||||
|
||||
function factory(player, initialList, initialIndex) {
|
||||
if (initialIndex === void 0) {
|
||||
initialIndex = 0;
|
||||
}
|
||||
|
||||
var list = null;
|
||||
var changing = false;
|
||||
/**
|
||||
* Get/set the playlist for a player.
|
||||
*
|
||||
* This function is added as an own property of the player and has its
|
||||
* own methods which can be called to manipulate the internal state.
|
||||
*
|
||||
* @param {Array} [newList]
|
||||
* If given, a new list of sources with which to populate the
|
||||
* playlist. Without this, the function acts as a getter.
|
||||
*
|
||||
* @param {number} [newIndex]
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Array}
|
||||
* The playlist
|
||||
*/
|
||||
|
||||
var playlist = player.playlist = function (newList, newIndex) {
|
||||
if (newIndex === void 0) {
|
||||
newIndex = 0;
|
||||
}
|
||||
|
||||
if (changing) {
|
||||
throw new Error('do not call playlist() during a playlist change');
|
||||
}
|
||||
|
||||
if (Array.isArray(newList)) {
|
||||
// @todo - Simplify this to `list.slice()` for v5.
|
||||
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
|
||||
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
|
||||
|
||||
changing = true;
|
||||
player.trigger({
|
||||
type: 'duringplaylistchange',
|
||||
nextIndex: newIndex,
|
||||
nextPlaylist: list,
|
||||
previousIndex: playlist.currentIndex_,
|
||||
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
|
||||
previousPlaylist: previousPlaylist || []
|
||||
});
|
||||
changing = false;
|
||||
|
||||
if (newIndex !== -1) {
|
||||
playlist.currentItem(newIndex);
|
||||
} // The only time the previous playlist is null is the first call to this
|
||||
// function. This allows us to fire the `duringplaylistchange` event
|
||||
// every time the playlist is populated and to maintain backward
|
||||
// compatibility by not firing the `playlistchange` event on the initial
|
||||
// population of the list.
|
||||
//
|
||||
// @todo - Remove this condition in preparation for v5.
|
||||
|
||||
|
||||
if (previousPlaylist) {
|
||||
player.setTimeout(function () {
|
||||
player.trigger('playlistchange');
|
||||
}, 0);
|
||||
}
|
||||
} // Always return a shallow clone of the playlist list.
|
||||
|
||||
|
||||
return list.slice();
|
||||
}; // On a new source, if there is no current item, disable auto-advance.
|
||||
|
||||
|
||||
player.on('loadstart', function () {
|
||||
if (playlist.currentItem() === -1) {
|
||||
reset(player);
|
||||
}
|
||||
});
|
||||
playlist.currentIndex_ = -1;
|
||||
playlist.player_ = player;
|
||||
playlist.autoadvance_ = {};
|
||||
playlist.repeat_ = false;
|
||||
/**
|
||||
* Get or set the current item in the playlist.
|
||||
*
|
||||
* During the duringplaylistchange event, acts only as a getter.
|
||||
*
|
||||
* @param {number} [index]
|
||||
* If given as a valid value, plays the playlist item at that index.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
playlist.currentItem = function (index) {
|
||||
// If the playlist is changing, only act as a getter.
|
||||
if (changing) {
|
||||
return playlist.currentIndex_;
|
||||
}
|
||||
|
||||
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
|
||||
playlist.currentIndex_ = index;
|
||||
playItem(playlist.player_, list[playlist.currentIndex_]);
|
||||
} else {
|
||||
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
|
||||
}
|
||||
|
||||
return playlist.currentIndex_;
|
||||
};
|
||||
/**
|
||||
* Checks if the playlist contains a value.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
|
||||
playlist.contains = function (value) {
|
||||
return playlist.indexOf(value) !== -1;
|
||||
};
|
||||
/**
|
||||
* Gets the index of a value in the playlist or -1 if not found.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to find the index of
|
||||
*
|
||||
* @return {number}
|
||||
* The index or -1
|
||||
*/
|
||||
|
||||
|
||||
playlist.indexOf = function (value) {
|
||||
if (typeof value === 'string') {
|
||||
return indexInSources(list, value);
|
||||
}
|
||||
|
||||
var sources = Array.isArray(value) ? value : value.sources;
|
||||
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var source = sources[i];
|
||||
|
||||
if (typeof source === 'string') {
|
||||
return indexInSources(list, source);
|
||||
} else if (source.src) {
|
||||
return indexInSources(list, source.src);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the current item in the playlist. This is identical to
|
||||
* calling `currentItem()` with no arguments.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
|
||||
playlist.currentIndex = function () {
|
||||
return playlist.currentItem();
|
||||
};
|
||||
/**
|
||||
* Get the index of the last item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the last item in the playlist or -1 if there are no
|
||||
* items.
|
||||
*/
|
||||
|
||||
|
||||
playlist.lastIndex = function () {
|
||||
return list.length - 1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the next item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the next item in the playlist or -1 if there is no
|
||||
* current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.nextIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
|
||||
|
||||
if (playlist.repeat_ && current === lastIndex) {
|
||||
return 0;
|
||||
} // Don't go past the end of the playlist.
|
||||
|
||||
|
||||
return Math.min(current + 1, lastIndex);
|
||||
};
|
||||
/**
|
||||
* Get the index of the previous item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the previous item in the playlist or -1 if there is
|
||||
* no current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previousIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
} // When repeating, loop back to the end of the playlist.
|
||||
|
||||
|
||||
if (playlist.repeat_ && current === 0) {
|
||||
return playlist.lastIndex();
|
||||
} // Don't go past the beginning of the playlist.
|
||||
|
||||
|
||||
return Math.max(current - 1, 0);
|
||||
};
|
||||
/**
|
||||
* Plays the first item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.first = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(0)];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the last item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.last = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(playlist.lastIndex())];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the next item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on last item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.next = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.nextIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays the previous item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on first item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previous = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.previousIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Set up auto-advance on the playlist.
|
||||
*
|
||||
* @param {number} [delay]
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*/
|
||||
|
||||
|
||||
playlist.autoadvance = function (delay) {
|
||||
setup(playlist.player_, delay);
|
||||
};
|
||||
/**
|
||||
* Sets `repeat` option, which makes the "next" video of the last video in
|
||||
* the playlist be the first video in the playlist.
|
||||
*
|
||||
* @param {boolean} [val]
|
||||
* The value to set repeat to
|
||||
*
|
||||
* @return {boolean}
|
||||
* The current value of repeat
|
||||
*/
|
||||
|
||||
|
||||
playlist.repeat = function (val) {
|
||||
if (val === undefined) {
|
||||
return playlist.repeat_;
|
||||
}
|
||||
|
||||
if (typeof val !== 'boolean') {
|
||||
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
|
||||
return;
|
||||
}
|
||||
|
||||
playlist.repeat_ = !!val;
|
||||
return playlist.repeat_;
|
||||
};
|
||||
/**
|
||||
* Sorts the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
|
||||
* @fires playlistsorted
|
||||
*
|
||||
* @param {Function} compare
|
||||
* A comparator function as per the native Array method.
|
||||
*/
|
||||
|
||||
|
||||
playlist.sort = function (compare) {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.sort(compare); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Reverses the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
|
||||
* @fires playlistsorted
|
||||
*/
|
||||
|
||||
|
||||
playlist.reverse = function () {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.reverse(); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Shuffle the contents of the list randomly.
|
||||
*
|
||||
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
|
||||
* @fires playlistsorted
|
||||
* @todo Make the `rest` option default to `true` in v5.0.0.
|
||||
* @param {Object} [options]
|
||||
* An object containing shuffle options.
|
||||
*
|
||||
* @param {boolean} [options.rest = false]
|
||||
* By default, the entire playlist is randomized. However, this may
|
||||
* not be desirable in all cases, such as when a user is already
|
||||
* watching a video.
|
||||
*
|
||||
* When `true` is passed for this option, it will only shuffle
|
||||
* playlist items after the current item. For example, when on the
|
||||
* first item, will shuffle the second item and beyond.
|
||||
*/
|
||||
|
||||
|
||||
playlist.shuffle = function (_temp) {
|
||||
var _ref = _temp === void 0 ? {} : _temp,
|
||||
rest = _ref.rest;
|
||||
|
||||
var index = 0;
|
||||
var arr = list; // When options.rest is true, start randomization at the item after the
|
||||
// current item.
|
||||
|
||||
if (rest) {
|
||||
index = playlist.currentIndex_ + 1;
|
||||
arr = list.slice(index);
|
||||
} // Bail if the array is empty or too short to shuffle.
|
||||
|
||||
|
||||
if (arr.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
|
||||
// the original array.
|
||||
|
||||
if (rest) {
|
||||
var _list;
|
||||
|
||||
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
|
||||
} // If the playlist is changing, don't trigger events.
|
||||
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
}; // If an initial list was given, populate the playlist with it.
|
||||
|
||||
|
||||
if (Array.isArray(initialList)) {
|
||||
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
|
||||
} else {
|
||||
list = [];
|
||||
}
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
var version = "4.2.6";
|
||||
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||
/**
|
||||
* The video.js playlist plugin. Invokes the playlist-maker to create a
|
||||
* playlist function on the specific player.
|
||||
*
|
||||
* @param {Array} list
|
||||
* a list of sources
|
||||
*
|
||||
* @param {number} item
|
||||
* The index to start at
|
||||
*/
|
||||
|
||||
var plugin = function plugin(list, item) {
|
||||
factory(this, list, item);
|
||||
};
|
||||
|
||||
registerPlugin('playlist', plugin);
|
||||
plugin.VERSION = version;
|
||||
|
||||
module.exports = plugin;
|
|
@ -1,763 +0,0 @@
|
|||
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
|
||||
import videojs from 'video.js';
|
||||
|
||||
/**
|
||||
* Validates a number of seconds to use as the auto-advance delay.
|
||||
*
|
||||
* @private
|
||||
* @param {number} s
|
||||
* The number to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether this is a valid second or not
|
||||
*/
|
||||
var validSeconds = function validSeconds(s) {
|
||||
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
|
||||
};
|
||||
/**
|
||||
* Resets the auto-advance behavior of a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to reset the behavior on
|
||||
*/
|
||||
|
||||
|
||||
var reset = function reset(player) {
|
||||
var aa = player.playlist.autoadvance_;
|
||||
|
||||
if (aa.timeout) {
|
||||
player.clearTimeout(aa.timeout);
|
||||
}
|
||||
|
||||
if (aa.trigger) {
|
||||
player.off('ended', aa.trigger);
|
||||
}
|
||||
|
||||
aa.timeout = null;
|
||||
aa.trigger = null;
|
||||
};
|
||||
/**
|
||||
* Sets up auto-advance behavior on a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* the current player
|
||||
*
|
||||
* @param {number} delay
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*
|
||||
* @return {undefined}
|
||||
* Used to short circuit function logic
|
||||
*/
|
||||
|
||||
|
||||
var setup = function setup(player, delay) {
|
||||
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
|
||||
// called with a valid value.
|
||||
|
||||
if (!validSeconds(delay)) {
|
||||
player.playlist.autoadvance_.delay = null;
|
||||
return;
|
||||
}
|
||||
|
||||
player.playlist.autoadvance_.delay = delay;
|
||||
|
||||
player.playlist.autoadvance_.trigger = function () {
|
||||
// This calls setup again, which will reset the existing auto-advance and
|
||||
// set up another auto-advance for the next "ended" event.
|
||||
var cancelOnPlay = function cancelOnPlay() {
|
||||
return setup(player, delay);
|
||||
}; // If there is a "play" event while we're waiting for an auto-advance,
|
||||
// we need to cancel the auto-advance. This could mean the user seeked
|
||||
// back into the content or restarted the content. This is reproducible
|
||||
// with an auto-advance > 0.
|
||||
|
||||
|
||||
player.one('play', cancelOnPlay);
|
||||
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
|
||||
reset(player);
|
||||
player.off('play', cancelOnPlay);
|
||||
player.playlist.next();
|
||||
}, delay * 1000);
|
||||
};
|
||||
|
||||
player.one('ended', player.playlist.autoadvance_.trigger);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all remote text tracks from a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to clear tracks on
|
||||
*/
|
||||
|
||||
var clearTracks = function clearTracks(player) {
|
||||
var tracks = player.remoteTextTracks();
|
||||
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
|
||||
// `TextTrackList` object is a live DOM list (not an array).
|
||||
|
||||
while (i--) {
|
||||
player.removeRemoteTextTrack(tracks[i]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays an item on a player's playlist.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to play the item on
|
||||
*
|
||||
* @param {Object} item
|
||||
* A source from the playlist.
|
||||
*
|
||||
* @return {Player}
|
||||
* The player that is now playing the item
|
||||
*/
|
||||
|
||||
|
||||
var playItem = function playItem(player, item) {
|
||||
var replay = !player.paused() || player.ended();
|
||||
player.trigger('beforeplaylistitem', item);
|
||||
player.poster(item.poster || '');
|
||||
player.src(item.sources);
|
||||
clearTracks(player);
|
||||
player.ready(function () {
|
||||
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
|
||||
player.trigger('playlistitem', item);
|
||||
|
||||
if (replay) {
|
||||
var playPromise = player.play(); // silence error when a pause interrupts a play request
|
||||
// on browsers which return a promise
|
||||
|
||||
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
|
||||
playPromise.then(null, function (e) {});
|
||||
}
|
||||
}
|
||||
|
||||
setup(player, player.playlist.autoadvance_.delay);
|
||||
});
|
||||
return player;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given two sources, check to see whether the two sources are equal.
|
||||
* If both source urls have a protocol, the protocols must match, otherwise, protocols
|
||||
* are ignored.
|
||||
*
|
||||
* @private
|
||||
* @param {string|Object} source1
|
||||
* The first source
|
||||
*
|
||||
* @param {string|Object} source2
|
||||
* The second source
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
var sourceEquals = function sourceEquals(source1, source2) {
|
||||
var src1 = source1;
|
||||
var src2 = source2;
|
||||
|
||||
if (typeof source1 === 'object') {
|
||||
src1 = source1.src;
|
||||
}
|
||||
|
||||
if (typeof source2 === 'object') {
|
||||
src2 = source2.src;
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src1)) {
|
||||
src2 = src2.slice(src2.indexOf('//'));
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src2)) {
|
||||
src1 = src1.slice(src1.indexOf('//'));
|
||||
}
|
||||
|
||||
return src1 === src2;
|
||||
};
|
||||
/**
|
||||
* Look through an array of playlist items for a specific `source`;
|
||||
* checking both the value of elements and the value of their `src`
|
||||
* property.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array of playlist items to look through
|
||||
*
|
||||
* @param {string} src
|
||||
* The source to look for
|
||||
*
|
||||
* @return {number}
|
||||
* The index of that source or -1
|
||||
*/
|
||||
|
||||
|
||||
var indexInSources = function indexInSources(arr, src) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var sources = arr[i].sources;
|
||||
|
||||
if (Array.isArray(sources)) {
|
||||
for (var j = 0; j < sources.length; j++) {
|
||||
var source = sources[j];
|
||||
|
||||
if (source && sourceEquals(source, src)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Randomize the contents of an array.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array.
|
||||
*
|
||||
* @return {Array}
|
||||
* The same array that was passed in.
|
||||
*/
|
||||
|
||||
|
||||
var randomize = function randomize(arr) {
|
||||
var index = -1;
|
||||
var lastIndex = arr.length - 1;
|
||||
|
||||
while (++index < arr.length) {
|
||||
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
|
||||
var value = arr[rand];
|
||||
arr[rand] = arr[index];
|
||||
arr[index] = value;
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
/**
|
||||
* Factory function for creating new playlist implementation on the given player.
|
||||
*
|
||||
* API summary:
|
||||
*
|
||||
* playlist(['a', 'b', 'c']) // setter
|
||||
* playlist() // getter
|
||||
* playlist.currentItem() // getter, 0
|
||||
* playlist.currentItem(1) // setter, 1
|
||||
* playlist.next() // 'c'
|
||||
* playlist.previous() // 'b'
|
||||
* playlist.first() // 'a'
|
||||
* playlist.last() // 'c'
|
||||
* playlist.autoadvance(5) // 5 second delay
|
||||
* playlist.autoadvance() // cancel autoadvance
|
||||
*
|
||||
* @param {Player} player
|
||||
* The current player
|
||||
*
|
||||
* @param {Array=} initialList
|
||||
* If given, an initial list of sources with which to populate
|
||||
* the playlist.
|
||||
*
|
||||
* @param {number=} initialIndex
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Function}
|
||||
* Returns the playlist function specific to the given player.
|
||||
*/
|
||||
|
||||
|
||||
function factory(player, initialList, initialIndex) {
|
||||
if (initialIndex === void 0) {
|
||||
initialIndex = 0;
|
||||
}
|
||||
|
||||
var list = null;
|
||||
var changing = false;
|
||||
/**
|
||||
* Get/set the playlist for a player.
|
||||
*
|
||||
* This function is added as an own property of the player and has its
|
||||
* own methods which can be called to manipulate the internal state.
|
||||
*
|
||||
* @param {Array} [newList]
|
||||
* If given, a new list of sources with which to populate the
|
||||
* playlist. Without this, the function acts as a getter.
|
||||
*
|
||||
* @param {number} [newIndex]
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Array}
|
||||
* The playlist
|
||||
*/
|
||||
|
||||
var playlist = player.playlist = function (newList, newIndex) {
|
||||
if (newIndex === void 0) {
|
||||
newIndex = 0;
|
||||
}
|
||||
|
||||
if (changing) {
|
||||
throw new Error('do not call playlist() during a playlist change');
|
||||
}
|
||||
|
||||
if (Array.isArray(newList)) {
|
||||
// @todo - Simplify this to `list.slice()` for v5.
|
||||
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
|
||||
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
|
||||
|
||||
changing = true;
|
||||
player.trigger({
|
||||
type: 'duringplaylistchange',
|
||||
nextIndex: newIndex,
|
||||
nextPlaylist: list,
|
||||
previousIndex: playlist.currentIndex_,
|
||||
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
|
||||
previousPlaylist: previousPlaylist || []
|
||||
});
|
||||
changing = false;
|
||||
|
||||
if (newIndex !== -1) {
|
||||
playlist.currentItem(newIndex);
|
||||
} // The only time the previous playlist is null is the first call to this
|
||||
// function. This allows us to fire the `duringplaylistchange` event
|
||||
// every time the playlist is populated and to maintain backward
|
||||
// compatibility by not firing the `playlistchange` event on the initial
|
||||
// population of the list.
|
||||
//
|
||||
// @todo - Remove this condition in preparation for v5.
|
||||
|
||||
|
||||
if (previousPlaylist) {
|
||||
player.setTimeout(function () {
|
||||
player.trigger('playlistchange');
|
||||
}, 0);
|
||||
}
|
||||
} // Always return a shallow clone of the playlist list.
|
||||
|
||||
|
||||
return list.slice();
|
||||
}; // On a new source, if there is no current item, disable auto-advance.
|
||||
|
||||
|
||||
player.on('loadstart', function () {
|
||||
if (playlist.currentItem() === -1) {
|
||||
reset(player);
|
||||
}
|
||||
});
|
||||
playlist.currentIndex_ = -1;
|
||||
playlist.player_ = player;
|
||||
playlist.autoadvance_ = {};
|
||||
playlist.repeat_ = false;
|
||||
/**
|
||||
* Get or set the current item in the playlist.
|
||||
*
|
||||
* During the duringplaylistchange event, acts only as a getter.
|
||||
*
|
||||
* @param {number} [index]
|
||||
* If given as a valid value, plays the playlist item at that index.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
playlist.currentItem = function (index) {
|
||||
// If the playlist is changing, only act as a getter.
|
||||
if (changing) {
|
||||
return playlist.currentIndex_;
|
||||
}
|
||||
|
||||
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
|
||||
playlist.currentIndex_ = index;
|
||||
playItem(playlist.player_, list[playlist.currentIndex_]);
|
||||
} else {
|
||||
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
|
||||
}
|
||||
|
||||
return playlist.currentIndex_;
|
||||
};
|
||||
/**
|
||||
* Checks if the playlist contains a value.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
|
||||
playlist.contains = function (value) {
|
||||
return playlist.indexOf(value) !== -1;
|
||||
};
|
||||
/**
|
||||
* Gets the index of a value in the playlist or -1 if not found.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to find the index of
|
||||
*
|
||||
* @return {number}
|
||||
* The index or -1
|
||||
*/
|
||||
|
||||
|
||||
playlist.indexOf = function (value) {
|
||||
if (typeof value === 'string') {
|
||||
return indexInSources(list, value);
|
||||
}
|
||||
|
||||
var sources = Array.isArray(value) ? value : value.sources;
|
||||
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var source = sources[i];
|
||||
|
||||
if (typeof source === 'string') {
|
||||
return indexInSources(list, source);
|
||||
} else if (source.src) {
|
||||
return indexInSources(list, source.src);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the current item in the playlist. This is identical to
|
||||
* calling `currentItem()` with no arguments.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
|
||||
playlist.currentIndex = function () {
|
||||
return playlist.currentItem();
|
||||
};
|
||||
/**
|
||||
* Get the index of the last item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the last item in the playlist or -1 if there are no
|
||||
* items.
|
||||
*/
|
||||
|
||||
|
||||
playlist.lastIndex = function () {
|
||||
return list.length - 1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the next item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the next item in the playlist or -1 if there is no
|
||||
* current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.nextIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
|
||||
|
||||
if (playlist.repeat_ && current === lastIndex) {
|
||||
return 0;
|
||||
} // Don't go past the end of the playlist.
|
||||
|
||||
|
||||
return Math.min(current + 1, lastIndex);
|
||||
};
|
||||
/**
|
||||
* Get the index of the previous item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the previous item in the playlist or -1 if there is
|
||||
* no current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previousIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
} // When repeating, loop back to the end of the playlist.
|
||||
|
||||
|
||||
if (playlist.repeat_ && current === 0) {
|
||||
return playlist.lastIndex();
|
||||
} // Don't go past the beginning of the playlist.
|
||||
|
||||
|
||||
return Math.max(current - 1, 0);
|
||||
};
|
||||
/**
|
||||
* Plays the first item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.first = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(0)];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the last item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.last = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(playlist.lastIndex())];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the next item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on last item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.next = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.nextIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays the previous item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on first item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previous = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.previousIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Set up auto-advance on the playlist.
|
||||
*
|
||||
* @param {number} [delay]
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*/
|
||||
|
||||
|
||||
playlist.autoadvance = function (delay) {
|
||||
setup(playlist.player_, delay);
|
||||
};
|
||||
/**
|
||||
* Sets `repeat` option, which makes the "next" video of the last video in
|
||||
* the playlist be the first video in the playlist.
|
||||
*
|
||||
* @param {boolean} [val]
|
||||
* The value to set repeat to
|
||||
*
|
||||
* @return {boolean}
|
||||
* The current value of repeat
|
||||
*/
|
||||
|
||||
|
||||
playlist.repeat = function (val) {
|
||||
if (val === undefined) {
|
||||
return playlist.repeat_;
|
||||
}
|
||||
|
||||
if (typeof val !== 'boolean') {
|
||||
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
|
||||
return;
|
||||
}
|
||||
|
||||
playlist.repeat_ = !!val;
|
||||
return playlist.repeat_;
|
||||
};
|
||||
/**
|
||||
* Sorts the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
|
||||
* @fires playlistsorted
|
||||
*
|
||||
* @param {Function} compare
|
||||
* A comparator function as per the native Array method.
|
||||
*/
|
||||
|
||||
|
||||
playlist.sort = function (compare) {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.sort(compare); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Reverses the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
|
||||
* @fires playlistsorted
|
||||
*/
|
||||
|
||||
|
||||
playlist.reverse = function () {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.reverse(); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Shuffle the contents of the list randomly.
|
||||
*
|
||||
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
|
||||
* @fires playlistsorted
|
||||
* @todo Make the `rest` option default to `true` in v5.0.0.
|
||||
* @param {Object} [options]
|
||||
* An object containing shuffle options.
|
||||
*
|
||||
* @param {boolean} [options.rest = false]
|
||||
* By default, the entire playlist is randomized. However, this may
|
||||
* not be desirable in all cases, such as when a user is already
|
||||
* watching a video.
|
||||
*
|
||||
* When `true` is passed for this option, it will only shuffle
|
||||
* playlist items after the current item. For example, when on the
|
||||
* first item, will shuffle the second item and beyond.
|
||||
*/
|
||||
|
||||
|
||||
playlist.shuffle = function (_temp) {
|
||||
var _ref = _temp === void 0 ? {} : _temp,
|
||||
rest = _ref.rest;
|
||||
|
||||
var index = 0;
|
||||
var arr = list; // When options.rest is true, start randomization at the item after the
|
||||
// current item.
|
||||
|
||||
if (rest) {
|
||||
index = playlist.currentIndex_ + 1;
|
||||
arr = list.slice(index);
|
||||
} // Bail if the array is empty or too short to shuffle.
|
||||
|
||||
|
||||
if (arr.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
|
||||
// the original array.
|
||||
|
||||
if (rest) {
|
||||
var _list;
|
||||
|
||||
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
|
||||
} // If the playlist is changing, don't trigger events.
|
||||
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
}; // If an initial list was given, populate the playlist with it.
|
||||
|
||||
|
||||
if (Array.isArray(initialList)) {
|
||||
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
|
||||
} else {
|
||||
list = [];
|
||||
}
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
var version = "4.2.6";
|
||||
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||
/**
|
||||
* The video.js playlist plugin. Invokes the playlist-maker to create a
|
||||
* playlist function on the specific player.
|
||||
*
|
||||
* @param {Array} list
|
||||
* a list of sources
|
||||
*
|
||||
* @param {number} item
|
||||
* The index to start at
|
||||
*/
|
||||
|
||||
var plugin = function plugin(list, item) {
|
||||
factory(this, list, item);
|
||||
};
|
||||
|
||||
registerPlugin('playlist', plugin);
|
||||
plugin.VERSION = version;
|
||||
|
||||
export default plugin;
|
|
@ -1,771 +0,0 @@
|
|||
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
|
||||
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
|
||||
(global.videojsPlaylist = factory(global.videojs));
|
||||
}(this, (function (videojs) { 'use strict';
|
||||
|
||||
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
|
||||
|
||||
/**
|
||||
* Validates a number of seconds to use as the auto-advance delay.
|
||||
*
|
||||
* @private
|
||||
* @param {number} s
|
||||
* The number to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether this is a valid second or not
|
||||
*/
|
||||
var validSeconds = function validSeconds(s) {
|
||||
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
|
||||
};
|
||||
/**
|
||||
* Resets the auto-advance behavior of a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to reset the behavior on
|
||||
*/
|
||||
|
||||
|
||||
var reset = function reset(player) {
|
||||
var aa = player.playlist.autoadvance_;
|
||||
|
||||
if (aa.timeout) {
|
||||
player.clearTimeout(aa.timeout);
|
||||
}
|
||||
|
||||
if (aa.trigger) {
|
||||
player.off('ended', aa.trigger);
|
||||
}
|
||||
|
||||
aa.timeout = null;
|
||||
aa.trigger = null;
|
||||
};
|
||||
/**
|
||||
* Sets up auto-advance behavior on a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* the current player
|
||||
*
|
||||
* @param {number} delay
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*
|
||||
* @return {undefined}
|
||||
* Used to short circuit function logic
|
||||
*/
|
||||
|
||||
|
||||
var setup = function setup(player, delay) {
|
||||
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
|
||||
// called with a valid value.
|
||||
|
||||
if (!validSeconds(delay)) {
|
||||
player.playlist.autoadvance_.delay = null;
|
||||
return;
|
||||
}
|
||||
|
||||
player.playlist.autoadvance_.delay = delay;
|
||||
|
||||
player.playlist.autoadvance_.trigger = function () {
|
||||
// This calls setup again, which will reset the existing auto-advance and
|
||||
// set up another auto-advance for the next "ended" event.
|
||||
var cancelOnPlay = function cancelOnPlay() {
|
||||
return setup(player, delay);
|
||||
}; // If there is a "play" event while we're waiting for an auto-advance,
|
||||
// we need to cancel the auto-advance. This could mean the user seeked
|
||||
// back into the content or restarted the content. This is reproducible
|
||||
// with an auto-advance > 0.
|
||||
|
||||
|
||||
player.one('play', cancelOnPlay);
|
||||
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
|
||||
reset(player);
|
||||
player.off('play', cancelOnPlay);
|
||||
player.playlist.next();
|
||||
}, delay * 1000);
|
||||
};
|
||||
|
||||
player.one('ended', player.playlist.autoadvance_.trigger);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all remote text tracks from a player.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to clear tracks on
|
||||
*/
|
||||
|
||||
var clearTracks = function clearTracks(player) {
|
||||
var tracks = player.remoteTextTracks();
|
||||
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
|
||||
// `TextTrackList` object is a live DOM list (not an array).
|
||||
|
||||
while (i--) {
|
||||
player.removeRemoteTextTrack(tracks[i]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays an item on a player's playlist.
|
||||
*
|
||||
* @param {Player} player
|
||||
* The player to play the item on
|
||||
*
|
||||
* @param {Object} item
|
||||
* A source from the playlist.
|
||||
*
|
||||
* @return {Player}
|
||||
* The player that is now playing the item
|
||||
*/
|
||||
|
||||
|
||||
var playItem = function playItem(player, item) {
|
||||
var replay = !player.paused() || player.ended();
|
||||
player.trigger('beforeplaylistitem', item);
|
||||
player.poster(item.poster || '');
|
||||
player.src(item.sources);
|
||||
clearTracks(player);
|
||||
player.ready(function () {
|
||||
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
|
||||
player.trigger('playlistitem', item);
|
||||
|
||||
if (replay) {
|
||||
var playPromise = player.play(); // silence error when a pause interrupts a play request
|
||||
// on browsers which return a promise
|
||||
|
||||
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
|
||||
playPromise.then(null, function (e) {});
|
||||
}
|
||||
}
|
||||
|
||||
setup(player, player.playlist.autoadvance_.delay);
|
||||
});
|
||||
return player;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given two sources, check to see whether the two sources are equal.
|
||||
* If both source urls have a protocol, the protocols must match, otherwise, protocols
|
||||
* are ignored.
|
||||
*
|
||||
* @private
|
||||
* @param {string|Object} source1
|
||||
* The first source
|
||||
*
|
||||
* @param {string|Object} source2
|
||||
* The second source
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
var sourceEquals = function sourceEquals(source1, source2) {
|
||||
var src1 = source1;
|
||||
var src2 = source2;
|
||||
|
||||
if (typeof source1 === 'object') {
|
||||
src1 = source1.src;
|
||||
}
|
||||
|
||||
if (typeof source2 === 'object') {
|
||||
src2 = source2.src;
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src1)) {
|
||||
src2 = src2.slice(src2.indexOf('//'));
|
||||
}
|
||||
|
||||
if (/^\/\//.test(src2)) {
|
||||
src1 = src1.slice(src1.indexOf('//'));
|
||||
}
|
||||
|
||||
return src1 === src2;
|
||||
};
|
||||
/**
|
||||
* Look through an array of playlist items for a specific `source`;
|
||||
* checking both the value of elements and the value of their `src`
|
||||
* property.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array of playlist items to look through
|
||||
*
|
||||
* @param {string} src
|
||||
* The source to look for
|
||||
*
|
||||
* @return {number}
|
||||
* The index of that source or -1
|
||||
*/
|
||||
|
||||
|
||||
var indexInSources = function indexInSources(arr, src) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var sources = arr[i].sources;
|
||||
|
||||
if (Array.isArray(sources)) {
|
||||
for (var j = 0; j < sources.length; j++) {
|
||||
var source = sources[j];
|
||||
|
||||
if (source && sourceEquals(source, src)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Randomize the contents of an array.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} arr
|
||||
* An array.
|
||||
*
|
||||
* @return {Array}
|
||||
* The same array that was passed in.
|
||||
*/
|
||||
|
||||
|
||||
var randomize = function randomize(arr) {
|
||||
var index = -1;
|
||||
var lastIndex = arr.length - 1;
|
||||
|
||||
while (++index < arr.length) {
|
||||
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
|
||||
var value = arr[rand];
|
||||
arr[rand] = arr[index];
|
||||
arr[index] = value;
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
/**
|
||||
* Factory function for creating new playlist implementation on the given player.
|
||||
*
|
||||
* API summary:
|
||||
*
|
||||
* playlist(['a', 'b', 'c']) // setter
|
||||
* playlist() // getter
|
||||
* playlist.currentItem() // getter, 0
|
||||
* playlist.currentItem(1) // setter, 1
|
||||
* playlist.next() // 'c'
|
||||
* playlist.previous() // 'b'
|
||||
* playlist.first() // 'a'
|
||||
* playlist.last() // 'c'
|
||||
* playlist.autoadvance(5) // 5 second delay
|
||||
* playlist.autoadvance() // cancel autoadvance
|
||||
*
|
||||
* @param {Player} player
|
||||
* The current player
|
||||
*
|
||||
* @param {Array=} initialList
|
||||
* If given, an initial list of sources with which to populate
|
||||
* the playlist.
|
||||
*
|
||||
* @param {number=} initialIndex
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Function}
|
||||
* Returns the playlist function specific to the given player.
|
||||
*/
|
||||
|
||||
|
||||
function factory(player, initialList, initialIndex) {
|
||||
if (initialIndex === void 0) {
|
||||
initialIndex = 0;
|
||||
}
|
||||
|
||||
var list = null;
|
||||
var changing = false;
|
||||
/**
|
||||
* Get/set the playlist for a player.
|
||||
*
|
||||
* This function is added as an own property of the player and has its
|
||||
* own methods which can be called to manipulate the internal state.
|
||||
*
|
||||
* @param {Array} [newList]
|
||||
* If given, a new list of sources with which to populate the
|
||||
* playlist. Without this, the function acts as a getter.
|
||||
*
|
||||
* @param {number} [newIndex]
|
||||
* If given, the index of the item in the list that should
|
||||
* be loaded first. If -1, no video is loaded. If omitted, The
|
||||
* the first video is loaded.
|
||||
*
|
||||
* @return {Array}
|
||||
* The playlist
|
||||
*/
|
||||
|
||||
var playlist = player.playlist = function (newList, newIndex) {
|
||||
if (newIndex === void 0) {
|
||||
newIndex = 0;
|
||||
}
|
||||
|
||||
if (changing) {
|
||||
throw new Error('do not call playlist() during a playlist change');
|
||||
}
|
||||
|
||||
if (Array.isArray(newList)) {
|
||||
// @todo - Simplify this to `list.slice()` for v5.
|
||||
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
|
||||
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
|
||||
|
||||
changing = true;
|
||||
player.trigger({
|
||||
type: 'duringplaylistchange',
|
||||
nextIndex: newIndex,
|
||||
nextPlaylist: list,
|
||||
previousIndex: playlist.currentIndex_,
|
||||
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
|
||||
previousPlaylist: previousPlaylist || []
|
||||
});
|
||||
changing = false;
|
||||
|
||||
if (newIndex !== -1) {
|
||||
playlist.currentItem(newIndex);
|
||||
} // The only time the previous playlist is null is the first call to this
|
||||
// function. This allows us to fire the `duringplaylistchange` event
|
||||
// every time the playlist is populated and to maintain backward
|
||||
// compatibility by not firing the `playlistchange` event on the initial
|
||||
// population of the list.
|
||||
//
|
||||
// @todo - Remove this condition in preparation for v5.
|
||||
|
||||
|
||||
if (previousPlaylist) {
|
||||
player.setTimeout(function () {
|
||||
player.trigger('playlistchange');
|
||||
}, 0);
|
||||
}
|
||||
} // Always return a shallow clone of the playlist list.
|
||||
|
||||
|
||||
return list.slice();
|
||||
}; // On a new source, if there is no current item, disable auto-advance.
|
||||
|
||||
|
||||
player.on('loadstart', function () {
|
||||
if (playlist.currentItem() === -1) {
|
||||
reset(player);
|
||||
}
|
||||
});
|
||||
playlist.currentIndex_ = -1;
|
||||
playlist.player_ = player;
|
||||
playlist.autoadvance_ = {};
|
||||
playlist.repeat_ = false;
|
||||
/**
|
||||
* Get or set the current item in the playlist.
|
||||
*
|
||||
* During the duringplaylistchange event, acts only as a getter.
|
||||
*
|
||||
* @param {number} [index]
|
||||
* If given as a valid value, plays the playlist item at that index.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
playlist.currentItem = function (index) {
|
||||
// If the playlist is changing, only act as a getter.
|
||||
if (changing) {
|
||||
return playlist.currentIndex_;
|
||||
}
|
||||
|
||||
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
|
||||
playlist.currentIndex_ = index;
|
||||
playItem(playlist.player_, list[playlist.currentIndex_]);
|
||||
} else {
|
||||
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
|
||||
}
|
||||
|
||||
return playlist.currentIndex_;
|
||||
};
|
||||
/**
|
||||
* Checks if the playlist contains a value.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to check
|
||||
*
|
||||
* @return {boolean}
|
||||
* The result
|
||||
*/
|
||||
|
||||
|
||||
playlist.contains = function (value) {
|
||||
return playlist.indexOf(value) !== -1;
|
||||
};
|
||||
/**
|
||||
* Gets the index of a value in the playlist or -1 if not found.
|
||||
*
|
||||
* @param {string|Object|Array} value
|
||||
* The value to find the index of
|
||||
*
|
||||
* @return {number}
|
||||
* The index or -1
|
||||
*/
|
||||
|
||||
|
||||
playlist.indexOf = function (value) {
|
||||
if (typeof value === 'string') {
|
||||
return indexInSources(list, value);
|
||||
}
|
||||
|
||||
var sources = Array.isArray(value) ? value : value.sources;
|
||||
|
||||
for (var i = 0; i < sources.length; i++) {
|
||||
var source = sources[i];
|
||||
|
||||
if (typeof source === 'string') {
|
||||
return indexInSources(list, source);
|
||||
} else if (source.src) {
|
||||
return indexInSources(list, source.src);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the current item in the playlist. This is identical to
|
||||
* calling `currentItem()` with no arguments.
|
||||
*
|
||||
* @return {number}
|
||||
* The current item index.
|
||||
*/
|
||||
|
||||
|
||||
playlist.currentIndex = function () {
|
||||
return playlist.currentItem();
|
||||
};
|
||||
/**
|
||||
* Get the index of the last item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the last item in the playlist or -1 if there are no
|
||||
* items.
|
||||
*/
|
||||
|
||||
|
||||
playlist.lastIndex = function () {
|
||||
return list.length - 1;
|
||||
};
|
||||
/**
|
||||
* Get the index of the next item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the next item in the playlist or -1 if there is no
|
||||
* current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.nextIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
|
||||
|
||||
if (playlist.repeat_ && current === lastIndex) {
|
||||
return 0;
|
||||
} // Don't go past the end of the playlist.
|
||||
|
||||
|
||||
return Math.min(current + 1, lastIndex);
|
||||
};
|
||||
/**
|
||||
* Get the index of the previous item in the playlist.
|
||||
*
|
||||
* @return {number}
|
||||
* The index of the previous item in the playlist or -1 if there is
|
||||
* no current item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previousIndex = function () {
|
||||
var current = playlist.currentItem();
|
||||
|
||||
if (current === -1) {
|
||||
return -1;
|
||||
} // When repeating, loop back to the end of the playlist.
|
||||
|
||||
|
||||
if (playlist.repeat_ && current === 0) {
|
||||
return playlist.lastIndex();
|
||||
} // Don't go past the beginning of the playlist.
|
||||
|
||||
|
||||
return Math.max(current - 1, 0);
|
||||
};
|
||||
/**
|
||||
* Plays the first item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.first = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(0)];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the last item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if the list is empty.
|
||||
*/
|
||||
|
||||
|
||||
playlist.last = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
return list[playlist.currentItem(playlist.lastIndex())];
|
||||
}
|
||||
|
||||
playlist.currentIndex_ = -1;
|
||||
};
|
||||
/**
|
||||
* Plays the next item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on last item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.next = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.nextIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Plays the previous item in the playlist.
|
||||
*
|
||||
* @return {Object|undefined}
|
||||
* Returns undefined and has no side effects if on first item.
|
||||
*/
|
||||
|
||||
|
||||
playlist.previous = function () {
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = playlist.previousIndex();
|
||||
|
||||
if (index !== playlist.currentIndex_) {
|
||||
return list[playlist.currentItem(index)];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Set up auto-advance on the playlist.
|
||||
*
|
||||
* @param {number} [delay]
|
||||
* The number of seconds to wait before each auto-advance.
|
||||
*/
|
||||
|
||||
|
||||
playlist.autoadvance = function (delay) {
|
||||
setup(playlist.player_, delay);
|
||||
};
|
||||
/**
|
||||
* Sets `repeat` option, which makes the "next" video of the last video in
|
||||
* the playlist be the first video in the playlist.
|
||||
*
|
||||
* @param {boolean} [val]
|
||||
* The value to set repeat to
|
||||
*
|
||||
* @return {boolean}
|
||||
* The current value of repeat
|
||||
*/
|
||||
|
||||
|
||||
playlist.repeat = function (val) {
|
||||
if (val === undefined) {
|
||||
return playlist.repeat_;
|
||||
}
|
||||
|
||||
if (typeof val !== 'boolean') {
|
||||
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
|
||||
return;
|
||||
}
|
||||
|
||||
playlist.repeat_ = !!val;
|
||||
return playlist.repeat_;
|
||||
};
|
||||
/**
|
||||
* Sorts the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
|
||||
* @fires playlistsorted
|
||||
*
|
||||
* @param {Function} compare
|
||||
* A comparator function as per the native Array method.
|
||||
*/
|
||||
|
||||
|
||||
playlist.sort = function (compare) {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.sort(compare); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Reverses the playlist array.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
|
||||
* @fires playlistsorted
|
||||
*/
|
||||
|
||||
|
||||
playlist.reverse = function () {
|
||||
// Bail if the array is empty.
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
list.reverse(); // If the playlist is changing, don't trigger events.
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
};
|
||||
/**
|
||||
* Shuffle the contents of the list randomly.
|
||||
*
|
||||
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
|
||||
* @fires playlistsorted
|
||||
* @todo Make the `rest` option default to `true` in v5.0.0.
|
||||
* @param {Object} [options]
|
||||
* An object containing shuffle options.
|
||||
*
|
||||
* @param {boolean} [options.rest = false]
|
||||
* By default, the entire playlist is randomized. However, this may
|
||||
* not be desirable in all cases, such as when a user is already
|
||||
* watching a video.
|
||||
*
|
||||
* When `true` is passed for this option, it will only shuffle
|
||||
* playlist items after the current item. For example, when on the
|
||||
* first item, will shuffle the second item and beyond.
|
||||
*/
|
||||
|
||||
|
||||
playlist.shuffle = function (_temp) {
|
||||
var _ref = _temp === void 0 ? {} : _temp,
|
||||
rest = _ref.rest;
|
||||
|
||||
var index = 0;
|
||||
var arr = list; // When options.rest is true, start randomization at the item after the
|
||||
// current item.
|
||||
|
||||
if (rest) {
|
||||
index = playlist.currentIndex_ + 1;
|
||||
arr = list.slice(index);
|
||||
} // Bail if the array is empty or too short to shuffle.
|
||||
|
||||
|
||||
if (arr.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
|
||||
// the original array.
|
||||
|
||||
if (rest) {
|
||||
var _list;
|
||||
|
||||
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
|
||||
} // If the playlist is changing, don't trigger events.
|
||||
|
||||
|
||||
if (changing) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Triggered after the playlist is sorted internally.
|
||||
*
|
||||
* @event playlistsorted
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
|
||||
player.trigger('playlistsorted');
|
||||
}; // If an initial list was given, populate the playlist with it.
|
||||
|
||||
|
||||
if (Array.isArray(initialList)) {
|
||||
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
|
||||
} else {
|
||||
list = [];
|
||||
}
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
var version = "4.2.6";
|
||||
|
||||
var registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||
/**
|
||||
* The video.js playlist plugin. Invokes the playlist-maker to create a
|
||||
* playlist function on the specific player.
|
||||
*
|
||||
* @param {Array} list
|
||||
* a list of sources
|
||||
*
|
||||
* @param {number} item
|
||||
* The index to start at
|
||||
*/
|
||||
|
||||
var plugin = function plugin(list, item) {
|
||||
factory(this, list, item);
|
||||
};
|
||||
|
||||
registerPlugin('playlist', plugin);
|
||||
plugin.VERSION = version;
|
||||
|
||||
return plugin;
|
||||
|
||||
})));
|
|
@ -1,2 +0,0 @@
|
|||
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],t):e.videojsPlaylist=t(e.videojs)}(this,function(e){"use strict";var t=function(e){var t=e.playlist.autoadvance_;t.timeout&&e.clearTimeout(t.timeout),t.trigger&&e.off("ended",t.trigger),t.timeout=null,t.trigger=null},r=function e(r,n){var i;(t(r),"number"==typeof(i=n)&&!isNaN(i)&&i>=0&&i<1/0)?(r.playlist.autoadvance_.delay=n,r.playlist.autoadvance_.trigger=function(){var i=function(){return e(r,n)};r.one("play",i),r.playlist.autoadvance_.timeout=r.setTimeout(function(){t(r),r.off("play",i),r.playlist.next()},1e3*n)},r.one("ended",r.playlist.autoadvance_.trigger)):r.playlist.autoadvance_.delay=null},n=function(e,t){var n=!e.paused()||e.ended();return e.trigger("beforeplaylistitem",t),e.poster(t.poster||""),e.src(t.sources),function(e){for(var t=e.remoteTextTracks(),r=t&&t.length||0;r--;)e.removeRemoteTextTrack(t[r])}(e),e.ready(function(){if((t.textTracks||[]).forEach(e.addRemoteTextTrack.bind(e)),e.trigger("playlistitem",t),n){var i=e.play();void 0!==i&&"function"==typeof i.then&&i.then(null,function(e){})}r(e,e.playlist.autoadvance_.delay)}),e},i=function(e,t){for(var r=0;r<e.length;r++){var n=e[r].sources;if(Array.isArray(n))for(var i=0;i<n.length;i++){var a=n[i];if(a&&(l=void 0,c=void 0,l=o=a,c=u=t,"object"==typeof o&&(l=o.src),"object"==typeof u&&(c=u.src),/^\/\//.test(l)&&(c=c.slice(c.indexOf("//"))),/^\/\//.test(c)&&(l=l.slice(l.indexOf("//"))),l===c))return r}}var o,u,l,c;return-1},a=function(e){for(var t=-1,r=e.length-1;++t<e.length;){var n=t+Math.floor(Math.random()*(r-t+1)),i=e[n];e[n]=e[t],e[t]=i}return e};var o=function(o,u){!function(o,u,l){void 0===l&&(l=0);var c=null,s=!1,d=o.playlist=function(e,t){if(void 0===t&&(t=0),s)throw new Error("do not call playlist() during a playlist change");if(Array.isArray(e)){var r=Array.isArray(c)?c.slice():null;c=e.slice(),s=!0,o.trigger({type:"duringplaylistchange",nextIndex:t,nextPlaylist:c,previousIndex:d.currentIndex_,previousPlaylist:r||[]}),s=!1,-1!==t&&d.currentItem(t),r&&o.setTimeout(function(){o.trigger("playlistchange")},0)}return c.slice()};o.on("loadstart",function(){-1===d.currentItem()&&t(o)}),d.currentIndex_=-1,d.player_=o,d.autoadvance_={},d.repeat_=!1,d.currentItem=function(e){return s?d.currentIndex_:("number"==typeof e&&d.currentIndex_!==e&&e>=0&&e<c.length?(d.currentIndex_=e,n(d.player_,c[d.currentIndex_])):d.currentIndex_=d.indexOf(d.player_.currentSrc()||""),d.currentIndex_)},d.contains=function(e){return-1!==d.indexOf(e)},d.indexOf=function(e){if("string"==typeof e)return i(c,e);for(var t=Array.isArray(e)?e:e.sources,r=0;r<t.length;r++){var n=t[r];if("string"==typeof n)return i(c,n);if(n.src)return i(c,n.src)}return-1},d.currentIndex=function(){return d.currentItem()},d.lastIndex=function(){return c.length-1},d.nextIndex=function(){var e=d.currentItem();if(-1===e)return-1;var t=d.lastIndex();return d.repeat_&&e===t?0:Math.min(e+1,t)},d.previousIndex=function(){var e=d.currentItem();return-1===e?-1:d.repeat_&&0===e?d.lastIndex():Math.max(e-1,0)},d.first=function(){if(!s)return c.length?c[d.currentItem(0)]:void(d.currentIndex_=-1)},d.last=function(){if(!s)return c.length?c[d.currentItem(d.lastIndex())]:void(d.currentIndex_=-1)},d.next=function(){if(!s){var e=d.nextIndex();return e!==d.currentIndex_?c[d.currentItem(e)]:void 0}},d.previous=function(){if(!s){var e=d.previousIndex();return e!==d.currentIndex_?c[d.currentItem(e)]:void 0}},d.autoadvance=function(e){r(d.player_,e)},d.repeat=function(t){return void 0===t?d.repeat_:"boolean"==typeof t?(d.repeat_=!!t,d.repeat_):void e.log.error("videojs-playlist: Invalid value for repeat",t)},d.sort=function(e){c.length&&(c.sort(e),s||o.trigger("playlistsorted"))},d.reverse=function(){c.length&&(c.reverse(),s||o.trigger("playlistsorted"))},d.shuffle=function(e){var t,r=(void 0===e?{}:e).rest,n=0,i=c;(r&&(n=d.currentIndex_+1,i=c.slice(n)),i.length<=1)||(a(i),r&&(t=c).splice.apply(t,[n,i.length].concat(i)),s||o.trigger("playlistsorted"))},Array.isArray(u)?d(u.slice(),l):c=[]}(this,o,u)};return((e=e&&e.hasOwnProperty("default")?e.default:e).registerPlugin||e.plugin)("playlist",o),o.VERSION="4.2.6",o});
|
|
@ -25,7 +25,7 @@ if (file_exists($extraPluginFile) && AVideoPlugin::isEnabledByName("Customize"))
|
|||
}
|
||||
|
||||
TimeLogEnd($timeLogHead, __LINE__);
|
||||
if (!empty($poster)) {
|
||||
if (!empty($poster) && !empty($video['description'])) {
|
||||
$subTitle = str_replace(['"', "\n", "\r"], ["", "", ""], strip_tags("{$video['description']}"));
|
||||
$custom = [];
|
||||
$custom[] = $subTitle;
|
||||
|
|
|
@ -376,7 +376,7 @@ TimeLogEnd($timeLogNameMY, __LINE__, $TimeLogLimitMY);
|
|||
include $global['systemRootPath'] . 'view/include/footer.php';
|
||||
TimeLogEnd($timeLogNameMY, __LINE__, $TimeLogLimitMY);
|
||||
?>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>plugin/PlayLists/videojs-playlist/videojs-playlist.js"></script>
|
||||
<script src="<?php echo getURL('view/js/BootstrapMenu.min.js'); ?>node_modules/videojs-playlist/dist/videojs-playlist.min.js"></script>
|
||||
<script>
|
||||
var fading = false;
|
||||
</script>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue