Removed extra <progress> for populating lower fill on range inputs

This commit is contained in:
Sam Potts 2017-10-18 12:43:10 +11:00
parent 4392abfc49
commit 36a84c5c2d
8 changed files with 342 additions and 382 deletions

View File

@ -3,19 +3,7 @@
"env": { "env": {
"browser": true "browser": true
}, },
"globals": { "globals": {},
"engine": true,
"Modernizr": false,
"ga": false,
"mixpanel": false,
"moment": false,
"fullscreen": false,
"Raven": false,
"templates": false,
"Hogan": false,
"locale_json": false,
"bootbox": false
},
"rules": { "rules": {
"no-const-assign": 1, "no-const-assign": 1,
"no-this-before-super": 1, "no-this-before-super": 1,

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,110 +1,88 @@
// ========================================================================== // ==========================================================================
// Gulp build script // Gulp build script
// ========================================================================== // ==========================================================================
/* global require, __dirname,Buffer */ /* global require, __dirname */
/* jshint -W079 */ /* eslint no-console: "off" */
/* beautify ignore:start */
var fs = require("fs"),
path = require("path"),
gulp = require("gulp"),
gutil = require("gulp-util"),
concat = require("gulp-concat"),
uglify = require("gulp-uglify"),
less = require("gulp-less"),
sass = require("gulp-sass"),
cleanCSS = require("gulp-clean-css"),
run = require("run-sequence"),
prefix = require("gulp-autoprefixer"),
svgstore = require("gulp-svgstore"),
svgmin = require("gulp-svgmin"),
rename = require("gulp-rename"),
s3 = require("gulp-s3"),
replace = require("gulp-replace"),
open = require("gulp-open"),
size = require("gulp-size"),
through = require("through2");
var root = __dirname, var fs = require('fs');
paths = { var path = require('path');
var gulp = require('gulp');
var gutil = require('gulp-util');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var less = require('gulp-less');
var sass = require('gulp-sass');
var cleanCSS = require('gulp-clean-css');
var run = require('run-sequence');
var prefix = require('gulp-autoprefixer');
var svgstore = require('gulp-svgstore');
var svgmin = require('gulp-svgmin');
var rename = require('gulp-rename');
var s3 = require('gulp-s3');
var replace = require('gulp-replace');
var open = require('gulp-open');
var size = require('gulp-size');
var root = __dirname;
var paths = {
plyr: { plyr: {
// Source paths // Source paths
src: { src: {
less: path.join(root, "src/less/**/*"), less: path.join(root, 'src/less/**/*'),
scss: path.join(root, "src/scss/**/*"), scss: path.join(root, 'src/scss/**/*'),
js: path.join(root, "src/js/**/*"), js: path.join(root, 'src/js/**/*'),
sprite: path.join(root, "src/sprite/*.svg") sprite: path.join(root, 'src/sprite/*.svg'),
}, },
// Output paths // Output paths
output: path.join(root, "dist/") output: path.join(root, 'dist/'),
}, },
demo: { demo: {
// Source paths // Source paths
src: { src: {
less: path.join(root, "demo/src/less/**/*"), less: path.join(root, 'demo/src/less/**/*'),
js: path.join(root, "demo/src/js/**/*"), js: path.join(root, 'demo/src/js/**/*'),
sprite: path.join(root, "demo/src/sprite/**/*") sprite: path.join(root, 'demo/src/sprite/**/*'),
}, },
// Output paths // Output paths
output: path.join(root, "demo/dist/"), output: path.join(root, 'demo/dist/'),
// Demo // Demo
root: path.join(root, "demo/") root: path.join(root, 'demo/'),
}, },
upload: [path.join(root, "dist/**"), path.join(root, "demo/dist/**")] upload: [path.join(root, 'dist/**'), path.join(root, 'demo/dist/**')],
}, };
// Task arrays // Task arrays
tasks = { var tasks = {
less: [], less: [],
scss: [], scss: [],
js: [], js: [],
sprite: [] sprite: [],
}, };
// Fetch bundles from JSON // Fetch bundles from JSON
bundles = loadJSON(path.join(root, "bundles.json")), var bundles = loadJSON(path.join(root, 'bundles.json'));
package = loadJSON(path.join(root, "package.json")); var package = loadJSON(path.join(root, 'package.json'));
// Load json // Load json
function loadJSON(path) { function loadJSON(path) {
try { try {
return JSON.parse(fs.readFileSync(path)); return JSON.parse(fs.readFileSync(path));
} } catch (err) {
catch(err) {
return {}; return {};
} }
} }
// Create a file from a string
// http://stackoverflow.com/questions/23230569/how-do-you-create-a-file-from-a-string-in-gulp
function createFile(filename, string) {
var src = require('stream').Readable({
objectMode: true
});
src._read = function () {
this.push(new gutil.File({
cwd: "",
base: "",
path: filename,
contents: new Buffer(string),
// stats also required for some functions
// https://nodejs.org/api/fs.html#fs_class_fs_stats
stat: {
size: string.length
}
}));
this.push(null);
}
return src
}
var build = { var build = {
js: function (files, bundle) { js: function(files, bundle) {
for (var key in files) { for (var key in files) {
(function(key) { (function(key) {
var name = "js-" + key; var name = 'js-' + key;
tasks.js.push(name); tasks.js.push(name);
gulp.task(name, function () { gulp.task(name, function() {
return gulp return gulp
.src(bundles[bundle].js[key]) .src(bundles[bundle].js[key])
.pipe(concat(key)) .pipe(concat(key))
@ -116,17 +94,17 @@ var build = {
}, },
less: function(files, bundle) { less: function(files, bundle) {
for (var key in files) { for (var key in files) {
(function (key) { (function(key) {
var name = "less-" + key; var name = 'less-' + key;
tasks.less.push(name); tasks.less.push(name);
gulp.task(name, function () { gulp.task(name, function() {
return gulp return gulp
.src(bundles[bundle].less[key]) .src(bundles[bundle].less[key])
.pipe(less()) .pipe(less())
.on("error", gutil.log) .on('error', gutil.log)
.pipe(concat(key)) .pipe(concat(key))
.pipe(prefix(["last 2 versions"], { cascade: false })) .pipe(prefix(['last 2 versions'], { cascade: false }))
.pipe(cleanCSS()) .pipe(cleanCSS())
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
@ -135,17 +113,17 @@ var build = {
}, },
scss: function(files, bundle) { scss: function(files, bundle) {
for (var key in files) { for (var key in files) {
(function (key) { (function(key) {
var name = "scss-" + key; var name = 'scss-' + key;
tasks.scss.push(name); tasks.scss.push(name);
gulp.task(name, function () { gulp.task(name, function() {
return gulp return gulp
.src(bundles[bundle].scss[key]) .src(bundles[bundle].scss[key])
.pipe(sass()) .pipe(sass())
.on("error", gutil.log) .on('error', gutil.log)
.pipe(concat(key)) .pipe(concat(key))
.pipe(prefix(["last 2 versions"], { cascade: false })) .pipe(prefix(['last 2 versions'], { cascade: false }))
.pipe(cleanCSS()) .pipe(cleanCSS())
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
@ -153,48 +131,52 @@ var build = {
} }
}, },
sprite: function(bundle) { sprite: function(bundle) {
var name = "sprite-" + bundle; var name = 'sprite-' + bundle;
tasks.sprite.push(name); tasks.sprite.push(name);
// Process Icons // Process Icons
gulp.task(name, function () { gulp.task(name, function() {
return gulp return gulp
.src(paths[bundle].src.sprite) .src(paths[bundle].src.sprite)
.pipe(svgmin({ .pipe(
plugins: [{ svgmin({
removeDesc: true plugins: [
}] {
})) removeDesc: true,
},
],
})
)
.pipe(svgstore()) .pipe(svgstore())
.pipe(rename({ basename: bundle })) .pipe(rename({ basename: bundle }))
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
} },
}; };
// Plyr core files // Plyr core files
build.js(bundles.plyr.js, "plyr"); build.js(bundles.plyr.js, 'plyr');
build.less(bundles.plyr.less, "plyr"); build.less(bundles.plyr.less, 'plyr');
build.scss(bundles.plyr.scss, "plyr"); build.scss(bundles.plyr.scss, 'plyr');
build.sprite("plyr"); build.sprite('plyr');
// Demo files // Demo files
build.less(bundles.demo.less, "demo"); build.less(bundles.demo.less, 'demo');
build.js(bundles.demo.js, "demo"); build.js(bundles.demo.js, 'demo');
build.sprite("demo"); build.sprite('demo');
// Build all JS // Build all JS
gulp.task("js", function(){ gulp.task('js', function() {
run(tasks.js); run(tasks.js);
}); });
// Build SCSS (for testing, default is LESS) // Build SCSS (for testing, default is LESS)
gulp.task("scss", function(){ gulp.task('scss', function() {
run(tasks.scss); run(tasks.scss);
}); });
// Watch for file changes // Watch for file changes
gulp.task("watch", function () { gulp.task('watch', function() {
// Plyr core // Plyr core
gulp.watch(paths.plyr.src.js, tasks.js); gulp.watch(paths.plyr.src.js, tasks.js);
gulp.watch(paths.plyr.src.less, tasks.less); gulp.watch(paths.plyr.src.less, tasks.less);
@ -207,90 +189,100 @@ gulp.task("watch", function () {
}); });
// Default gulp task // Default gulp task
gulp.task("default", function(){ gulp.task('default', function() {
run(tasks.js, tasks.less, tasks.sprite, "watch"); run(tasks.js, tasks.less, tasks.sprite, 'watch');
}); });
// Publish a version to CDN and demo // Publish a version to CDN and demo
// -------------------------------------------- // --------------------------------------------
// Some options // Some options
var aws = loadJSON(path.join(root, "aws.json")), var aws = loadJSON(path.join(root, 'aws.json'));
version = package.version, var version = package.version;
maxAge = 31536000, // seconds 1 year var maxAge = 31536000; // 1 year
options = { var options = {
cdn: { cdn: {
headers: { headers: {
"Cache-Control": "max-age=" + maxAge, 'Cache-Control': 'max-age=' + maxAge,
"Vary": "Accept-Encoding" Vary: 'Accept-Encoding',
} },
}, },
demo: { demo: {
headers: { headers: {
"Cache-Control": "no-cache, no-store, must-revalidate, max-age=0", 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
"Vary": "Accept-Encoding" Vary: 'Accept-Encoding',
} },
}, },
symlinks: function(version, filename) { symlinks: function(version, filename) {
return { return {
headers: { headers: {
// http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
"x-amz-website-redirect-location": "/" + version + "/" + filename, 'x-amz-website-redirect-location': '/' + version + '/' + filename,
"Cache-Control": "no-cache, no-store, must-revalidate, max-age=0" 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
} },
} };
} },
}; };
// If aws is setup // If aws is setup
if("cdn" in aws) { if ('cdn' in aws) {
var regex = "(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:\.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:\.[\\da-z\\-]+)*)?", var regex =
cdnpath = new RegExp(aws.cdn.domain + "\/" + regex, "gi"), '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?';
semver = new RegExp("v" + regex, "gi"), var cdnpath = new RegExp(aws.cdn.domain + '/' + regex, 'gi');
localPath = new RegExp("(\.\.\/)?dist", "gi"), var semver = new RegExp('v' + regex, 'gi');
versionPath = "https://" + aws.cdn.domain + "/" + version; var localPath = new RegExp('(../)?dist', 'gi');
var versionPath = 'https://' + aws.cdn.domain + '/' + version;
} }
// Publish version to CDN bucket // Publish version to CDN bucket
gulp.task("cdn", function () { gulp.task('cdn', function() {
console.log("Uploading " + version + " to " + aws.cdn.domain + "..."); console.log('Uploading ' + version + ' to ' + aws.cdn.domain + '...');
// Upload to CDN // Upload to CDN
return gulp.src(paths.upload) return gulp
.pipe(size({ .src(paths.upload)
showFiles: true, .pipe(
gzip: true size({
})) showFiles: true,
.pipe(rename(function (path) { gzip: true,
path.dirname = path.dirname.replace(".", version); })
})) )
.pipe(
rename(function(path) {
path.dirname = path.dirname.replace('.', version);
})
)
.pipe(replace(localPath, versionPath)) .pipe(replace(localPath, versionPath))
.pipe(s3(aws.cdn, options.cdn)); .pipe(s3(aws.cdn, options.cdn));
}); });
// Publish to demo bucket // Publish to demo bucket
gulp.task("demo", function () { gulp.task('demo', function() {
console.log("Uploading " + version + " demo to " + aws.demo.domain + "..."); console.log('Uploading ' + version + ' demo to ' + aws.demo.domain + '...');
// Replace versioned files in readme.md // Replace versioned files in readme.md
gulp.src([root + "/readme.md"]) gulp
.pipe(replace(cdnpath, aws.cdn.domain + "/" + version)) .src([root + '/readme.md'])
.pipe(replace(cdnpath, aws.cdn.domain + '/' + version))
.pipe(gulp.dest(root)); .pipe(gulp.dest(root));
// Replace versioned files in plyr.js // Replace versioned files in plyr.js
gulp.src(path.join(root, "src/js/plyr.js")) gulp
.pipe(replace(semver, "v" + version)) .src(path.join(root, 'src/js/plyr.js'))
.pipe(replace(cdnpath, aws.cdn.domain + "/" + version)) .pipe(replace(semver, 'v' + version))
.pipe(gulp.dest(path.join(root, "src/js/"))); .pipe(replace(cdnpath, aws.cdn.domain + '/' + version))
.pipe(gulp.dest(path.join(root, 'src/js/')));
// Replace local file paths with remote paths in demo HTML // Replace local file paths with remote paths in demo HTML
// e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js" // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
gulp.src([paths.demo.root + "*.html"]) gulp
.src([paths.demo.root + '*.html'])
.pipe(replace(localPath, versionPath)) .pipe(replace(localPath, versionPath))
.pipe(s3(aws.demo, options.demo)); .pipe(s3(aws.demo, options.demo));
// Upload error.html to cdn (as well as demo site) // Upload error.html to cdn (as well as demo site)
return gulp.src([paths.demo.root + "error.html"]) return gulp
.src([paths.demo.root + 'error.html'])
.pipe(replace(localPath, versionPath)) .pipe(replace(localPath, versionPath))
.pipe(s3(aws.cdn, options.demo)); .pipe(s3(aws.cdn, options.demo));
}); });
@ -319,21 +311,20 @@ gulp.task("demo", function () {
});*/ });*/
// Open the demo site to check it's sweet // Open the demo site to check it's sweet
gulp.task("open", function () { gulp.task('open', function() {
console.log("Opening " + aws.demo.domain + "..."); console.log('Opening ' + aws.demo.domain + '...');
// A file must be specified or gulp will skip the task // A file must be specified or gulp will skip the task
// Doesn't matter which file since we set the URL above // Doesn't matter which file since we set the URL above
// Weird, I know... // Weird, I know...
return gulp.src([paths.demo.root + "index.html"]) return gulp.src([paths.demo.root + 'index.html']).pipe(
.pipe(open("", { open('', {
url: "http://" + aws.demo.domain url: 'http://' + aws.demo.domain,
})); })
);
}); });
// Do everything // Do everything
gulp.task("publish", function () { gulp.task('publish', function() {
run(tasks.js, tasks.less, tasks.sprite, "cdn", "demo"); run(tasks.js, tasks.less, tasks.sprite, 'cdn', 'demo');
}); });
/* beautify ignore:end */

View File

@ -471,6 +471,7 @@
isFirefox: isFirefox, isFirefox: isFirefox,
isChrome: isChrome, isChrome: isChrome,
isSafari: isSafari, isSafari: isSafari,
isWebkit: 'WebkitAppearance' in document.documentElement.style,
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),
}; };
@ -1429,6 +1430,45 @@
} }
} }
// Webkit polyfill for lower fill range
function updateRangeFill(range) {
if (!player.browser.isWebkit) {
return;
}
if (!utils.is.htmlElement(range)) {
return;
}
// Inject the stylesheet if needed
if (!utils.is.htmlElement(player.elements.styleSheet)) {
player.elements.styleSheet = utils.createElement('style');
player.elements.container.appendChild(player.elements.styleSheet);
}
var styleSheet = player.elements.styleSheet.sheet;
var percentage = (range.value / range.max) * 100;
var selector = '#' + range.id + '::-webkit-slider-runnable-track';
var styles = '{ background-image: linear-gradient(to right, currentColor ' + percentage + '%, transparent ' + percentage + '%) }';
var index = -1;
// Find old rule if it exists
[].some.call(styleSheet.rules, function(rule, i) {
if (rule.selectorText === selector) {
index = i;
return true;
}
})[0];
// Remove old rule
if (index !== -1) {
styleSheet.deleteRule(index);
}
// Insert new one
styleSheet.insertRule([selector, styles].join(' '));
}
// Get icon URL // Get icon URL
function getIconUrl() { function getIconUrl() {
return { return {
@ -1605,7 +1645,7 @@
type: 'range', type: 'range',
min: 0, min: 0,
max: 100, max: 100,
step: 0.1, step: 0.01,
value: 0, value: 0,
autocomplete: 'off', autocomplete: 'off',
}, },
@ -1738,14 +1778,11 @@
container.appendChild(seek.label); container.appendChild(seek.label);
container.appendChild(seek.input); container.appendChild(seek.input);
// TODO: Add loop display indicator
// Played progress
container.appendChild(createProgress('played'));
// Buffer progress // Buffer progress
container.appendChild(createProgress('buffer')); container.appendChild(createProgress('buffer'));
// TODO: Add loop display indicator
// Seek tooltip // Seek tooltip
if (player.config.tooltips.seek) { if (player.config.tooltips.seek) {
var tooltip = utils.createElement( var tooltip = utils.createElement(
@ -1803,10 +1840,6 @@
volume.appendChild(range.label); volume.appendChild(range.label);
volume.appendChild(range.input); volume.appendChild(range.input);
// Create the display progress
var progress = createProgress('volume', attributes);
volume.appendChild(progress);
controls.appendChild(volume); controls.appendChild(volume);
} }
@ -2701,8 +2734,6 @@
// Display // Display
player.elements.display = { player.elements.display = {
buffer: getElement(player.config.selectors.display.buffer), buffer: getElement(player.config.selectors.display.buffer),
played: getElement(player.config.selectors.display.played),
volume: getElement(player.config.selectors.display.volume),
duration: getElement(player.config.selectors.display.duration), duration: getElement(player.config.selectors.display.duration),
currentTime: getElement(player.config.selectors.display.currentTime), currentTime: getElement(player.config.selectors.display.currentTime),
}; };
@ -3043,7 +3074,6 @@
// Get current quality // Get current quality
player.media.quality = instance.getPlaybackQuality(); player.media.quality = instance.getPlaybackQuality();
// Trigger timeupdate
trigger(player.media, 'qualitychange'); trigger(player.media, 'qualitychange');
}, },
onPlaybackRateChange: function(event) { onPlaybackRateChange: function(event) {
@ -3053,7 +3083,6 @@
// Get current speed // Get current speed
player.media.playbackRate = instance.getPlaybackRate(); player.media.playbackRate = instance.getPlaybackRate();
// Trigger timeupdate
trigger(player.media, 'ratechange'); trigger(player.media, 'ratechange');
}, },
onReady: function(event) { onReady: function(event) {
@ -3097,10 +3126,7 @@
// Update UI // Update UI
embedReady(); embedReady();
// Trigger timeupdate
trigger(player.media, 'timeupdate'); trigger(player.media, 'timeupdate');
// Trigger timeupdate
trigger(player.media, 'durationchange'); trigger(player.media, 'durationchange');
// Reset timer // Reset timer
@ -3177,10 +3203,7 @@
// Poll to get playback progress // Poll to get playback progress
timers.playing = window.setInterval(function() { timers.playing = window.setInterval(function() {
// Set the current time
player.media.currentTime = instance.getCurrentTime(); player.media.currentTime = instance.getCurrentTime();
// Trigger timeupdate
trigger(player.media, 'timeupdate'); trigger(player.media, 'timeupdate');
}, 100); }, 100);
@ -3248,15 +3271,11 @@
player.embed.getCurrentTime().then(function(value) { player.embed.getCurrentTime().then(function(value) {
player.media.currentTime = value; player.media.currentTime = value;
// Trigger timeupdate
trigger(player.media, 'timeupdate'); trigger(player.media, 'timeupdate');
}); });
player.embed.getDuration().then(function(value) { player.embed.getDuration().then(function(value) {
player.media.duration = value; player.media.duration = value;
// Trigger timeupdate
trigger(player.media, 'durationchange'); trigger(player.media, 'durationchange');
}); });
@ -3358,8 +3377,6 @@
player.embed.getPosition(function(value) { player.embed.getPosition(function(value) {
player.media.currentTime = value; player.media.currentTime = value;
// Trigger timeupdate
trigger(player.media, 'timeupdate'); trigger(player.media, 'timeupdate');
}); });
@ -3554,10 +3571,7 @@
var value = player.media.muted ? 0 : player.media.volume; var value = player.media.muted ? 0 : player.media.volume;
if (player.elements.inputs.volume) { if (player.elements.inputs.volume) {
player.elements.inputs.volume.value = value; setRange(player.elements.inputs.volume, value);
}
if (player.elements.display.volume) {
player.elements.display.volume.value = value;
} }
} }
@ -3592,78 +3606,28 @@
}, player.loading ? 250 : 0); }, player.loading ? 250 : 0);
} }
// Update <progress> elements // Update seek value and lower fill
function updateProgress(event) { function setRange(range, value) {
if (!player.supported.full) { if (!utils.is.htmlElement(range)) {
return; return;
} }
var progress = player.elements.display.played; range.value = value;
var value = 0;
var duration = player.getDuration();
if (event) { // Webkit range fill
switch (event.type) { updateRangeFill(range);
// Video playing
case 'timeupdate':
case 'seeking':
value = utils.getPercentage(player.media.currentTime, duration);
// Set seek range value only if it's a 'natural' time event
if (event.type === 'timeupdate' && player.elements.inputs.seek) {
player.elements.inputs.seek.value = value;
}
break;
// Check buffer status
case 'playing':
case 'progress':
progress = player.elements.display.buffer;
value = (function() {
var buffered = player.media.buffered;
if (buffered && buffered.length) {
// HTML5
return utils.getPercentage(buffered.end(0), duration);
} else if (utils.is.number(buffered)) {
// YouTube returns between 0 and 1
return buffered * 100;
}
return 0;
})();
break;
}
}
// TODO: Loop - this shouldn't be here
/*if (utils.is.number(player.config.loop.start) && utils.is.number(player.config.loop.end) && player.media.currentTime >= player.config.loop.end) {
console.warn('Looping');
player.seek(player.config.loop.start);
}*/
setProgress(progress, value);
} }
// Set <progress> value // Set <progress> value
function setProgress(progress, value) { function setProgress(progress, value) {
if (!player.supported.full) {
return;
}
// Default to 0 // Default to 0
if (utils.is.undefined(value)) { if (utils.is.undefined(value)) {
value = 0; value = 0;
} }
// Default to buffer or bail // Default to buffer or bail
if (utils.is.undefined(progress)) { if (utils.is.undefined(progress)) {
if (utils.is.htmlElement(player.elements.display.buffer)) { progress = player.elements.display.buffer;
progress = player.elements.display.buffer;
} else {
return;
}
} }
// Update value and label // Update value and label
@ -3678,10 +3642,63 @@
} }
} }
// Update <progress> elements
function updateProgress(event) {
if (!player.supported.full) {
return;
}
var value = 0;
var duration = player.getDuration();
if (event) {
switch (event.type) {
// Video playing
case 'timeupdate':
case 'seeking':
value = utils.getPercentage(player.media.currentTime, duration);
// Set seek range value only if it's a 'natural' time event
if (event.type === 'timeupdate') {
setRange(player.elements.inputs.seek, value);
}
break;
// Check buffer status
case 'playing':
case 'progress':
value = (function() {
var buffered = player.media.buffered;
if (buffered && buffered.length) {
// HTML5
return utils.getPercentage(buffered.end(0), duration);
} else if (utils.is.number(buffered)) {
// YouTube returns between 0 and 1
return buffered * 100;
}
return 0;
})();
setProgress(player.elements.display.buffer, value);
break;
}
}
// TODO: Loop - this shouldn't be here
/*if (utils.is.number(player.config.loop.start) && utils.is.number(player.config.loop.end) && player.media.currentTime >= player.config.loop.end) {
console.warn('Looping');
player.seek(player.config.loop.start);
}*/
}
// Update the displayed time // Update the displayed time
function updateTimeDisplay(time, element) { function updateTimeDisplay(time, element) {
// Bail if there's no duration display // Bail if there's no duration display
if (!element) { if (!utils.is.htmlElement(element)) {
return; return;
} }
@ -3749,27 +3766,6 @@
updateProgress(event); updateProgress(event);
} }
// Update seek range and progress
function updateSeekDisplay(time) {
// Default to 0
if (!utils.is.number(time)) {
time = 0;
}
var duration = player.getDuration();
var value = utils.getPercentage(time, duration);
// Update progress
if (player.elements.progress && player.elements.display.played) {
player.elements.display.played.value = value;
}
// Update seek range input
if (player.elements.buttons && player.elements.inputs.seek) {
player.elements.inputs.seek.value = value;
}
}
// Update hover tooltip for seeking // Update hover tooltip for seeking
function updateSeekTooltip(event) { function updateSeekTooltip(event) {
var duration = player.getDuration(); var duration = player.getDuration();
@ -3828,17 +3824,13 @@
return; return;
} }
// Update seek range and progress
updateSeekDisplay();
// Reset buffer progress
setProgress();
// Cancel current network requests // Cancel current network requests
cancelRequests(); cancelRequests();
// Destroy instance and re-setup // Destroy instance and re-setup
player.destroy(function() { player.destroy(function() {
// TODO: Reset menus here
// Remove elements // Remove elements
removeElement(player.media); removeElement(player.media);
removeElement('captions'); removeElement('captions');
@ -3977,7 +3969,7 @@
var target = player.elements.buttons[play ? 'pause' : 'play']; var target = player.elements.buttons[play ? 'pause' : 'play'];
// Transfer focus // Transfer focus
if (target) { if (utils.is.htmlElement(target)) {
target.focus(); target.focus();
} }
} }
@ -4262,11 +4254,12 @@
// Click anywhere closes menu // Click anywhere closes menu
utils.on(document.documentElement, 'click', toggleMenu); utils.on(document.documentElement, 'click', toggleMenu);
// Show tab in menu // Settings menu
utils.on(player.elements.settings.form, 'click', showTab);
// Settings menu items - use event delegation as items are added/removed
utils.on(player.elements.settings.form, 'click', function(event) { utils.on(player.elements.settings.form, 'click', function(event) {
// Show tab in menu
showTab(event);
// Settings menu items - use event delegation as items are added/removed
// Settings - Language // Settings - Language
if (utils.matches(event.target, player.config.selectors.inputs.language)) { if (utils.matches(event.target, player.config.selectors.inputs.language)) {
handlerProxy.call(this, event, player.config.listeners.language, function() { handlerProxy.call(this, event, player.config.listeners.language, function() {
@ -4306,11 +4299,18 @@
player.seek(event.target.value / event.target.max * duration); player.seek(event.target.value / event.target.max * duration);
}); });
// Seek // Volume
utils.proxy(player.elements.inputs.volume, inputEvent, player.config.listeners.volume, function() { utils.proxy(player.elements.inputs.volume, inputEvent, player.config.listeners.volume, function() {
player.setVolume(event.target.value); player.setVolume(event.target.value);
}); });
// Polyfill for lower fill in <input type="range"> for webkit
if (player.browser.isWebkit) {
utils.on(getElements('input[type="range"]'), [inputEvent, 'updated'].join(' '), function(event) {
updateRangeFill(event.target);
});
}
// Seek tooltip // Seek tooltip
utils.on(player.elements.progress, 'mouseenter mouseleave mousemove', updateSeekTooltip); utils.on(player.elements.progress, 'mouseenter mouseleave mousemove', updateSeekTooltip);
@ -4789,7 +4789,6 @@
setupCaptions: setupCaptions, setupCaptions: setupCaptions,
toggleNativeControls: toggleNativeControls, toggleNativeControls: toggleNativeControls,
updateTimeDisplay: updateTimeDisplay, updateTimeDisplay: updateTimeDisplay,
updateSeekDisplay: updateSeekDisplay,
updateSource: updateSource, updateSource: updateSource,
toggleMenu: toggleMenu, toggleMenu: toggleMenu,
timers: timers, timers: timers,
@ -4925,9 +4924,6 @@
targetTime = duration; targetTime = duration;
} }
// Update seek range and progress
player.core.updateSeekDisplay(targetTime);
// Set the current time // Set the current time
// Embeds // Embeds
if (utils.inArray(types.embed, player.type)) { if (utils.inArray(types.embed, player.type)) {
@ -4949,9 +4945,6 @@
player.pause(); player.pause();
} }
// Trigger timeupdate
player.core.trigger(player.media, 'timeupdate');
// Set seeking flag // Set seeking flag
player.media.seeking = true; player.media.seeking = true;
@ -5196,7 +5189,7 @@
player.config.loop.end = null; player.config.loop.end = null;
} }
player.config.loop.start = currentTime; player.config.loop.start = currentTime;
player.config.loop.indicator.start = player.elements.display.played.value; //player.config.loop.indicator.start = player.elements.display.played.value;
break; break;
case 'end': case 'end':
@ -5204,7 +5197,7 @@
return; return;
} }
player.config.loop.end = currentTime; player.config.loop.end = currentTime;
player.config.loop.indicator.end = player.elements.display.played.value; //player.config.loop.indicator.end = player.elements.display.played.value;
break; break;
case 'all': case 'all':

View File

@ -18,7 +18,7 @@
background: @plyr-range-thumb-bg; background: @plyr-range-thumb-bg;
border: @plyr-range-thumb-border; border: @plyr-range-thumb-border;
border-radius: 100%; border-radius: 100%;
transition: background .2s ease, border .2s ease, transform .2s ease; transition: background 0.2s ease, border 0.2s ease, transform 0.2s ease;
box-shadow: @plyr-range-thumb-shadow; box-shadow: @plyr-range-thumb-shadow;
box-sizing: border-box; box-sizing: border-box;
} }

View File

@ -1,6 +1,7 @@
// ========================================================================== // ==========================================================================
// Plyr styles // Plyr styles
// https://github.com/sampotts/plyr // https://github.com/sampotts/plyr
// TODO: break into smaller files and look at use of BEM classnames
// ========================================================================== // ==========================================================================
@import 'variables'; @import 'variables';
@ -57,7 +58,7 @@
} }
// ARIA // ARIA
[aria-hidden="true"] { [aria-hidden='true'] {
display: none; display: none;
} }
@ -77,7 +78,7 @@
// Range inputs // Range inputs
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
input[type="range"] { input[type='range'] {
display: block; display: block;
height: (@plyr-range-thumb-height * @plyr-range-thumb-active-scale); height: (@plyr-range-thumb-height * @plyr-range-thumb-active-scale);
width: 100%; width: 100%;
@ -87,6 +88,9 @@
border: none; border: none;
background: transparent; background: transparent;
// Used in JS to populate lower fill for WebKit
color: @plyr-range-selected-bg;
// WebKit // WebKit
-webkit-appearance: none; -webkit-appearance: none;
@ -106,6 +110,11 @@
&::-moz-range-thumb { &::-moz-range-thumb {
.plyr-range-thumb(); .plyr-range-thumb();
} }
&::-moz-range-progress {
height: @plyr-range-track-height;
background: currentColor;
border-radius: (@plyr-range-track-height / 2);
}
// Microsoft // Microsoft
&::-ms-track { &::-ms-track {
@ -119,7 +128,7 @@
} }
&::-ms-fill-lower { &::-ms-fill-lower {
.plyr-range-track(); .plyr-range-track();
background: @plyr-range-selected-bg; background: currentColor;
} }
&::-ms-thumb { &::-ms-thumb {
.plyr-range-thumb(); .plyr-range-thumb();
@ -157,13 +166,37 @@
} }
// Video range inputs // Video range inputs
.plyr--video input[type="range"].tab-focus { .plyr--video input[type='range'] {
outline: 1px dotted fade(@plyr-video-control-color, 50%); &::-webkit-slider-runnable-track {
background: @plyr-video-range-track-bg;
}
&::-moz-range-track {
background: @plyr-video-range-track-bg;
}
&::-ms-track {
background: @plyr-video-range-track-bg;
}
&.tab-focus {
outline: 1px dotted fade(@plyr-video-control-color, 50%);
}
} }
// Audio range inputs // Audio range inputs
.plyr--audio input[type="range"].tab-focus { .plyr--audio input[type='range'] {
outline: 1px dotted fade(@plyr-audio-control-color, 50%); &::-webkit-slider-runnable-track {
background: @plyr-audio-range-track-bg;
}
&::-moz-range-track {
background: @plyr-audio-range-track-bg;
}
&::-ms-track {
background: @plyr-audio-range-track-bg;
}
&.tab-focus {
outline: 1px dotted fade(@plyr-audio-control-color, 50%);
}
} }
// Screen reader only elements // Screen reader only elements
@ -354,7 +387,6 @@
display: block; display: block;
fill: currentColor; fill: currentColor;
pointer-events: none; pointer-events: none;
filter: drop-shadow(0 1px 1px fade(#000, 15%));
} }
// Hide toggle icons by default // Hide toggle icons by default
@ -378,17 +410,21 @@
bottom: 0; bottom: 0;
z-index: 2; z-index: 2;
padding: (@plyr-control-spacing * 3.5) @plyr-control-spacing @plyr-control-spacing; padding: (@plyr-control-spacing * 3.5) @plyr-control-spacing @plyr-control-spacing;
background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 85%)); background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 70%));
border-bottom-left-radius: inherit; border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit; border-bottom-right-radius: inherit;
color: @plyr-video-control-color; color: @plyr-video-control-color;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
.plyr__control { .plyr__control {
svg {
filter: drop-shadow(0 1px 1px fade(#000, 15%));
}
// Hover and tab focus // Hover and tab focus
&.tab-focus, &.tab-focus,
&:hover, &:hover,
&[aria-expanded="true"] { &[aria-expanded='true'] {
background: @plyr-video-control-bg-hover; background: @plyr-video-control-bg-hover;
color: @plyr-video-control-color-hover; color: @plyr-video-control-color-hover;
} }
@ -407,7 +443,7 @@
// Hover and tab focus // Hover and tab focus
&.tab-focus, &.tab-focus,
&:hover, &:hover,
&[aria-expanded="true"] { &[aria-expanded='true'] {
background: @plyr-audio-control-bg-hover; background: @plyr-audio-control-bg-hover;
color: @plyr-audio-control-color-hover; color: @plyr-audio-control-color-hover;
} }
@ -461,11 +497,11 @@
} }
// States // States
.plyr__controls [data-plyr="pause"], .plyr__controls [data-plyr='pause'],
.plyr--playing .plyr__controls [data-plyr="play"] { .plyr--playing .plyr__controls [data-plyr='play'] {
display: none; display: none;
} }
.plyr--playing .plyr__controls [data-plyr="pause"] { .plyr--playing .plyr__controls [data-plyr='pause'] {
display: inline-block; display: inline-block;
} }
@ -481,16 +517,16 @@
} }
// Some options are hidden by default // Some options are hidden by default
.plyr [data-plyr="captions"], .plyr [data-plyr='captions'],
.plyr [data-plyr="fullscreen"], .plyr [data-plyr='fullscreen'],
.plyr [data-plyr="pip"], .plyr [data-plyr='pip'],
.plyr [data-plyr="airplay"] { .plyr [data-plyr='airplay'] {
display: none; display: none;
} }
.plyr--captions-enabled [data-plyr="captions"], .plyr--captions-enabled [data-plyr='captions'],
.plyr--fullscreen-enabled [data-plyr="fullscreen"], .plyr--fullscreen-enabled [data-plyr='fullscreen'],
.plyr--pip-enabled [data-plyr="pip"], .plyr--pip-enabled [data-plyr='pip'],
.plyr--airplay-enabled [data-plyr="airplay"] { .plyr--airplay-enabled [data-plyr='airplay'] {
display: inline-block; display: inline-block;
} }
@ -503,7 +539,7 @@
.plyr__control svg { .plyr__control svg {
transition: transform 0.3s ease; transition: transform 0.3s ease;
} }
.plyr__control[aria-expanded="true"] { .plyr__control[aria-expanded='true'] {
svg { svg {
transform: rotate(45deg); transform: rotate(45deg);
} }
@ -668,7 +704,7 @@
&::before { &::before {
// Arrows // Arrows
content: ""; content: '';
position: absolute; position: absolute;
width: 0; width: 0;
height: 0; height: 0;
@ -739,16 +775,6 @@
input[type='range'] { input[type='range'] {
position: relative; position: relative;
z-index: 2; z-index: 2;
&::-webkit-slider-runnable-track {
background: transparent;
}
&::-moz-range-track {
background: transparent;
}
&::-ms-fill-upper {
background: transparent;
}
} }
// Seek tooltip to show time // Seek tooltip to show time
@ -760,9 +786,7 @@
display: inline-block; display: inline-block;
} }
.plyr__progress--buffer, .plyr__progress--buffer {
.plyr__progress--played,
.plyr__volume--display {
position: absolute; position: absolute;
left: 0; left: 0;
top: 50%; top: 50%;
@ -770,8 +794,7 @@
height: @plyr-range-track-height; height: @plyr-range-track-height;
margin: -(@plyr-range-track-height / 2) 0 0; margin: -(@plyr-range-track-height / 2) 0 0;
padding: 0; padding: 0;
vertical-align: top; background: transparent;
border: none; border: none;
border-radius: 100px; border-radius: 100px;
@ -799,31 +822,6 @@
border-radius: 100px; border-radius: 100px;
} }
} }
.plyr__progress--played,
.plyr__volume--display {
z-index: 1;
color: @plyr-range-selected-bg;
background: transparent;
transition: none;
&::-webkit-progress-value {
min-width: @plyr-range-track-height;
max-width: 99%;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: none;
}
&::-moz-progress-bar {
min-width: @plyr-range-track-height;
max-width: 99%;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
transition: none;
}
&::-ms-fill {
display: none;
}
}
.plyr__progress--buffer { .plyr__progress--buffer {
&::-webkit-progress-value { &::-webkit-progress-value {
transition: width 0.2s ease; transition: width 0.2s ease;
@ -835,18 +833,10 @@
transition: width 0.2s ease; transition: width 0.2s ease;
} }
} }
.plyr--video .plyr__progress--buffer,
.plyr--video .plyr__volume--display {
background: @plyr-video-range-track-bg;
box-shadow: 0 1px 1px fade(#000, 15%);
}
.plyr--video .plyr__progress--buffer { .plyr--video .plyr__progress--buffer {
box-shadow: 0 1px 1px fade(#000, 15%);
color: @plyr-video-progress-buffered-bg; color: @plyr-video-progress-buffered-bg;
} }
.plyr--audio .plyr__progress--buffer,
.plyr--audio .plyr__volume--display {
background: @plyr-audio-range-track-bg;
}
.plyr--audio .plyr__progress--buffer { .plyr--audio .plyr__progress--buffer {
color: @plyr-audio-progress-buffered-bg; color: @plyr-audio-progress-buffered-bg;
} }
@ -892,7 +882,7 @@
// Add a slash in before // Add a slash in before
&::before { &::before {
content: "\2044"; content: '\2044';
margin-right: @plyr-control-spacing; margin-right: @plyr-control-spacing;
} }
} }
@ -926,7 +916,7 @@
// It's not supported to change volume using JavaScript: // It's not supported to change volume using JavaScript:
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
.plyr--is-ios .plyr__volume, .plyr--is-ios .plyr__volume,
.plyr--is-ios [data-plyr="mute"] { .plyr--is-ios [data-plyr='mute'] {
display: none !important; display: none !important;
} }

View File

@ -29,8 +29,8 @@
// Controls // Controls
@plyr-control-icon-size: 18px; @plyr-control-icon-size: 18px;
@plyr-control-spacing: 10px; @plyr-control-spacing: 10px;
@plyr-control-padding: (@plyr-control-spacing * .7); @plyr-control-padding: (@plyr-control-spacing * 0.7);
@plyr-video-controls-bg: #343f4a; @plyr-video-controls-bg: #000;
@plyr-video-control-color: #fff; @plyr-video-control-color: #fff;
@plyr-video-control-color-hover: #fff; @plyr-video-control-color-hover: #fff;
@plyr-video-control-bg-hover: @plyr-color-main; @plyr-video-control-bg-hover: @plyr-color-main;
@ -55,10 +55,8 @@
// Progress // Progress
@plyr-progress-loading-size: 25px; @plyr-progress-loading-size: 25px;
@plyr-progress-loading-bg: fade(#343f4a, 20%); @plyr-progress-loading-bg: fade(#343f4a, 20%);
@plyr-video-progress-bg: fade(#fff, 25%); @plyr-video-progress-buffered-bg: fade(#fff, 25%);
@plyr-video-progress-buffered-bg: @plyr-video-progress-bg; @plyr-audio-progress-buffered-bg: fade(#c6d6db, 66%);
@plyr-audio-progress-bg: fade(#c6d6db, 66%);
@plyr-audio-progress-buffered-bg: @plyr-audio-progress-bg;
// Range sliders // Range sliders
@plyr-range-track-height: 8px; @plyr-range-track-height: 8px;