<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<style>
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
padding: 0;
display: flex;
flex-flow: column nowrap;
min-height: 100vh;
background: linear-gradient(135def, #7c1599 0%, #921099 48%, #7e4ae8 100%);
background-size: cover;
align-items: center;
justify-content: center;
}
.cover {
max-width: 750px;
border: 5px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
position: relative;
font-size: 0;
overflow: hidden;
}
.video {
width: 100%;
}
.toggle {
background: none;
border: 0;
line-height: 1;
color: white;
text-align: center;
outline: 0;
padding: 0;
cursor: pointer;
max-width: 50px;
}
.toggle:focus {
border-color: #ffc600;
}
.volume {
width: 10px;
height: 30px;
}
.panel {
display: flex;
position: absolute;
bottom: 0;
width: 100%;
transform: translateY(100%) translateY(-5px);
transition: all 0.3s;
flex-wrap: wrap;
background: rgba(0, 0, 0, 0.1);
z-index: 2147483648;
left: 0;
}
.cover:hover .panel,
.panel.active {
transform: translateY(0);
}
.panel:hover .progress,
.panel.active .progress {
height: 15px;
}
.panel > * {
flex: 1;
}
.progress {
flex: 10;
position: relative;
display: flex;
flex-basis: 100%;
height: 5px;
transition: height 0.3s;
background: rgba(0, 0, 0, 0.5);
cursor: ew-resize;
}
.bar {
width: 50%;
background: #ffc600;
flex: 0;
flex-basis: 50%;
}
/* unholy css to style input type="range" */
input[type=range] {
-webkit-appearance: none;
background: transparent;
width: 100%;
margin: 12px 3px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
background: rgba(255, 255, 255, 0.8);
border-radius: 1.3px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0);
height: 1.5em;
width: 1.5em;
border-radius: 20px;
background: #ffc600;
cursor: pointer;
-webkit-appearance: none;
margin-top: -8px;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #ffc600;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 3px;
cursor: pointer;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
background: #fff;
border-radius: 1.3px;
border: 0.2px solid rgba(1, 1, 1, 0);
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
height: 1.5em;
width: 1.5em;
border: 0;
border-radius: 20px;
background: #ffc600;
cursor: pointer;
}
/* full screen button styling */
.fullscreen {
margin-right: 7px;
background: none;
border: 1px solid white;
border: 0;
line-height: 1;
color: white;
text-align: center;
outline: 0;
padding: 0 0 5px 0;
cursor: pointer;
max-width: 30px;
font-size: 1.3rem;
}
/* Because video needed a defined hieght in order for object-fit: fill to work. */
video {
height: 100%;
object-fit: fill;
}
/* hide the default Chrome video player styling */
video::-webkit-media-controls-overlay-enclosure {
display: none !important;
}
video::-webkit-media-controls-enclosure {
display: none !important;
}
video::-webkit-media-controls {
display: none !important;
}
/* Needed to hide player controls in Safari Only */
video::-webkit-media-controls-panel {
display: none !important;
}
video::-webkit-media-controls-play-button {
display: none !important;
}
video::-webkit-media-controls-current-time-display {
display: none !important;
}
video::-webkit-media-controls-time-remaining-display {
display: none !important;
}
video::-webkit-media-controls-timeline {
display: none !important;
}
video::-webkit-media-controls-mute-button {
display: none !important;
}
video::-webkit-media-controls-volume-slider {
display: none !important;
}
video::-webkit-media-controls-fullscreen-button {
display: none !important;
}
video::-internal-media-controls-download-button {
display: none !important;
}
/* Firefox Shadow DOM Fix */
*::-moz-list-bullet,
*::-moz-list-number {
display: none !important;
}
*::-moz-meter-bar {
display: none !important;
}
:-moz-full-screen:not(:root)::backdrop {
display: none !important;
}
*::backdrop {
display: none !important;
}
:fullscreen:not(:root) {
display: none !important;
}
/* New addition to removal of User Agent StyleSheet for Firefox. Removed dotted border around range. */
input[type="range"]::-moz-focus-outer {
border: 0;
}
</style>
</head>
<body>
<div id='V0' class='cover'></div>
<div id='V1' class='cover'></div>
<div id='V2' class='cover'></div>
<div id='V3' class='cover'></div>
<template id='controls'>
<div class="panel">
<div class="progress">
<div class="bar"></div>
</div>
<button class="toggle" title="Play/Pause">
<i class="fa fa-play fa-3x"></i>
</button>
<input type="range" class="volume" min="0" max="1" step="0.05" value="0.70">
<button class='fullscreen'>
<i class='fa fa-expand fa-2x'></i>
</button>
</div>
</template>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var mp4 = ['005609.mp4', '005610.mp4', '005611.mp4', '005612.mp4'];
var webm = ['041157.mp4', '041153.mp4', '041154.mp4', '041156.mp4'];
function init(VMp4, VWebm) {
var VArray = Array.from(document.querySelectorAll('.cover'));
VArray.map(function(V, idx) {
var ID = V.id;
return players(ID, idx, VMp4, VWebm);
});
}
function players(id, IDX, vMp4, vWebm) {
var V = document.getElementById(id);
console.log(V);
var frag = document.createDocumentFragment();
var tag = document.createElement('video');
var src0 = document.createElement('source');
var src1 = document.createElement('source');
tag.classList.add('video');
tag.controls = false;
tag.width = '320';
tag.style.background = '#000';
tag.poster = `https://gincore.net/images/video-play-2.png`;
// Set Paths
var mUrl = `https://storage04.dropshots.com/photos6000/photos/1381926/20170326/`;
var wUrl = `https://storage04.dropshots.com/photos7000/photos/1381926/20180214/`;
src0.type = 'video/mp4';
src1.type = 'video/webm';
src0.src = mUrl + vMp4[IDX];
src1.src = wUrl + vWebm[IDX];
frag.appendChild(tag);
tag.appendChild(src0);
tag.appendChild(src1);
V.appendChild(frag);
var controls = document.querySelector('#controls').content;
var clone = document.importNode(controls, true);
V.appendChild(clone);
}
init(mp4, webm);
$(".cover").each(function() {
var C = $(this)[0].id;
var $ctl = $(this).find('.panel');
var $vid = $(this).find('.video');
var $tog = $(this).find('.toggle');
var $prg = $(this).find('.progress');
var $bar = $(this).find('.bar');
var $vol = $(this).find('.volume');
var $tfs = $(this).find('.fullscreen')
var ctl = $ctl[0];
var vid = $vid[0];
var tog = $tog[0];
var prg = $prg[0];
var bar = $bar[0];
var vol = $vol[0];
var tfs = $tfs[0];
function togglePlay() {
var playPause = vid.paused ? 'play' : 'pause';
vid[playPause]();
$tog.find('.fa').toggleClass('fa-play fa-pause');
}
function updateVolume() {
vid.volume = this.value;
}
function updateProgress() {
var perc = (vid.currentTime / vid.duration) * 100;
bar.style.flexBasis = `${perc}%`;
}
function seekTrack(e) {
var seekTime = (e.offsetX / prg.offsetWidth) * vid.duration;
vid.currentTime = seekTime;
}
var isFullScreen = function() {
return !!(document.webkitFullscreenElement || document.mozFullScreenElement || document.fullscreenElement);
};
function toggleFS() {
if (!isFullScreen()) {
if (vid.requestFullscreen) {
vid.requestFullscreen();
} else if (vid.webkitRequestFullScreen) {
vid.webkitRequestFullScreen();
} else if (document.getElementById(C).mozRequestFullScreen) {
document.getElementById(C).mozRequestFullScreen();
} else if (vid.msRequestFullscreen) {
vid.msRequestFullscreen();
}
$tfs.find('.fa').removeClass('fa-expand').addClass('fa-compress');
$ctl.removeClass('active');
$('.panel').css('z-index', '-1');
$('#' + C + " .panel").css('z-index',"2147483648");
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msCancelFullscreen) {
document.msCancelFullscreen();
}
$tfs.find('.fa').addClass('fa-expand').removeClass('fa-compress');
if (!vid.pause || !vid.ended) {
$ctl.addClass('active');
}
$('.panel').css('z-index', '2147483648');
}
}
function go() {
$ctl.addClass('active');
$tog.find('.fa').removeClass('fa-play').addClass('fa-pause');
}
function stop() {
$ctl.removeClass('active');
$tog.find('.fa').removeClass('fa-pause').addClass('fa-play');
}
$vid.on('click', togglePlay);
$tog.on('click', togglePlay);
$vid.on('timeupdate', updateProgress);
$vid.on('playing', go);
$vid.on('ended pause', stop);
$vol.on('input', updateVolume);
var mousedown = false;
$prg.on('click', seekTrack);
$prg.on('mousemove', function(e) {
mousedown && seekTrack(e);
});
$prg.on('mousedown', function() {
mousedown = true;
});
$prg.on('mouseup', function() {
mousedown = false;
});
$tfs.on('click', toggleFS);
});
</script>
</body>
</html>
// Code goes here
/* Styles go here */
SO48693832
==========
[Need to show HTML5 Video Controls on Hover or Play](https://stackoverflow.com/a/48735388/2813224)
--------------------------------------------------
###Line No.
- 64 ------ `.panel` is the replaces native controls - [`z-index: 2147483648`](https://stackoverflow.com/a/25461690/2813224) is one more than the native controls
- 77 ------ The `.active` class is responsible for `.panel`'s visibility.
- 110 - 165 Browser style hacks to style `.volume` slider
- 190 - 237 These vendor prefixed rules are to override Webkit browser defaults
- 240 - 251 To fix Firefox DOM shadow styles.
- 271 - 277 Each `div.cover` will be a video player upon pageload. I got the idea working with JWPlayer.
- 279 - 292 [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) tag contains dormant code markup for each of the players' custom controls. It is active when lines 338-339 are invoked.
- 296 - 297 Place your MP4/WebM filenames in these 2 arrays. Note: webm[] has \*.mp4 because the site that hosts the video files do not recognize WebM extension so I changed \*.webm to \*.mp4 files. Normally the webm array should have files with the *.webm extension.
- 301 - 307 Collect all `.cover` and the 2 filename arrays.
- 309 - 341 Dynamically create all of the players.
- 346 - 356 Reference the elements as jQuery Objects.
- 358 - 364 [Dereference the jQuery Objects as plain JavaScript Objects.](https://stackoverflow.com/a/5533784/2813224)
- 366 - 421 Core functions
- 402 - 404 Kills `.active` class and hides the rest of the `.panel`s
from bleeding trough in full screen mode.
- 415 - 419 If going from full screen to normal mode, ensure player is `.active` while playing. Restore the rest of the players to original `z-index`.
- 423 - 431 `go()` and `stop()` functions are primarily responsible for the visibility for the `.panel`
- 433 - 563 Event handlers
- 439 - 441 The state of the video can be summed up with three events:
`playing`, `ended`, and `pause`. The callback functions are `go()` and `stop()`.