├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .nvmrc ├── .travis.yml ├── .whitesource ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── poster.jpg ├── scripts ├── karma.conf.js ├── postcss.config.js └── rollup.config.js ├── src ├── guid.js ├── plugin.js └── plugin.scss └── test └── plugin.test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_style = space 8 | indent_size = 2 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | Briefly describe the issue. 3 | Include a [reduced test case](https://css-tricks.com/reduced-test-cases/). 4 | 5 | ## Steps to reproduce 6 | Explain in detail the exact steps necessary to reproduce the issue. 7 | 8 | 1. 9 | 2. 10 | 3. 11 | 12 | ## Results 13 | ### Expected 14 | Please describe what you expected to see. 15 | 16 | ### Actual 17 | Please describe what actually happened. 18 | 19 | ### Error output 20 | If there are any errors at all, please include them here. 21 | 22 | ## Additional Information 23 | Please include any additional information necessary here. Including the following: 24 | 25 | ### versions 26 | #### videojs 27 | what version of videojs does this occur with? 28 | 29 | #### browsers 30 | what browser are affected? 31 | 32 | #### OSes 33 | what platforms (operating systems and devices) are affected? 34 | 35 | ### plugins 36 | are any videojs plugins being used on the page? If so, please list them below. 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | Please describe the change as necessary. 3 | If it's a feature or enhancement please be as detailed as possible. 4 | If it's a bug fix, please link the issue that it fixes or describe the bug in as much detail. 5 | 6 | ## Specific Changes proposed 7 | Please list the specific changes involved in this pull request. 8 | 9 | ## Requirements Checklist 10 | - [ ] Feature implemented / Bug fixed 11 | - [ ] If necessary, more likely in a feature request than a bug fix 12 | - [ ] Unit Tests updated or fixed 13 | - [ ] Docs/guides updated 14 | - [ ] Reviewed by Two Core Contributors 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | Thumbs.db 3 | ehthumbs.db 4 | Desktop.ini 5 | .DS_Store 6 | ._* 7 | 8 | # Editors 9 | *~ 10 | *.swp 11 | *.tmproj 12 | *.tmproject 13 | *.sublime-* 14 | .idea/ 15 | .project/ 16 | .settings/ 17 | .vscode/ 18 | 19 | # Logs 20 | logs 21 | *.log 22 | npm-debug.log* 23 | 24 | # Dependency directories 25 | bower_components/ 26 | node_modules/ 27 | 28 | # Build-related directories 29 | dist/ 30 | docs/api/ 31 | test/dist/ 32 | .eslintcache 33 | .yo-rc.json 34 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Intentionally left blank, so that npm does not ignore anything by default, 2 | # but relies on the package.json "files" array to explicitly define what ends 3 | # up in the package. 4 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/fermium 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | dist: trusty 3 | language: node_js 4 | # node version is specified using the .nvmrc file 5 | before_install: 6 | - npm install -g greenkeeper-lockfile@1 7 | before_script: 8 | - export DISPLAY=:99.0 9 | - sh -e /etc/init.d/xvfb start 10 | - greenkeeper-lockfile-update 11 | after_script: 12 | - greenkeeper-lockfile-upload 13 | addons: 14 | firefox: latest 15 | chrome: stable 16 | 17 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "settingsInheritedFrom": "brightcove/whitesource-config@main" 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [3.0.0](https://github.com/brightcove/videojs-dock/compare/v2.2.0...v3.0.0) (2021-12-17) 3 | 4 | ### Chores 5 | 6 | * Update generate-rollup-config to drop older browser support ([#77](https://github.com/brightcove/videojs-dock/issues/77)) ([e862def](https://github.com/brightcove/videojs-dock/commit/e862def)) 7 | * update other dependencies ([#125](https://github.com/brightcove/videojs-dock/issues/125)) ([deaa9d8](https://github.com/brightcove/videojs-dock/commit/deaa9d8)) 8 | 9 | 10 | ### BREAKING CHANGES 11 | 12 | * update build to no longer support IE11 and other older browsers. 13 | 14 | Co-authored-by: Alex Barstow 15 | 16 | 17 | # [2.2.0](https://github.com/brightcove/videojs-dock/compare/v2.1.4...v2.2.0) (2021-05-17) 18 | 19 | ### Features 20 | 21 | * add player labelledBy and describedBy aria based on title and description elements ([#69](https://github.com/brightcove/videojs-dock/issues/69)) ([7c1e7ba](https://github.com/brightcove/videojs-dock/commit/7c1e7ba)) 22 | 23 | ### Bug Fixes 24 | 25 | * create elements on player ready ([#66](https://github.com/brightcove/videojs-dock/issues/66)) ([2aae663](https://github.com/brightcove/videojs-dock/commit/2aae663)), closes [#54](https://github.com/brightcove/videojs-dock/issues/54) 26 | * keep player's label in labelledby list ([#70](https://github.com/brightcove/videojs-dock/issues/70)) ([b585d71](https://github.com/brightcove/videojs-dock/commit/b585d71)) 27 | 28 | ### Chores 29 | 30 | * **nvmrc:** update * to fermium ([#60](https://github.com/brightcove/videojs-dock/issues/60)) ([7ec04de](https://github.com/brightcove/videojs-dock/commit/7ec04de)) 31 | * **package:** update npm-run-all/videojs-generator-verify for security ([57bee79](https://github.com/brightcove/videojs-dock/commit/57bee79)) 32 | 33 | 34 | ## [2.1.4](https://github.com/brightcove/videojs-dock/compare/v2.1.3...v2.1.4) (2018-09-18) 35 | 36 | ### Bug Fixes 37 | 38 | * export the version on the plugin ([#30](https://github.com/brightcove/videojs-dock/issues/30)) ([5d3c3ea](https://github.com/brightcove/videojs-dock/commit/5d3c3ea)) 39 | 40 | 41 | ## [2.1.3](https://github.com/brightcove/videojs-dock/compare/v2.1.2...v2.1.3) (2018-09-12) 42 | 43 | ### Bug Fixes 44 | 45 | * Remove the postinstall script to prevent install issues ([#27](https://github.com/brightcove/videojs-dock/issues/27)) ([621a4d0](https://github.com/brightcove/videojs-dock/commit/621a4d0)) 46 | 47 | ### Chores 48 | 49 | * update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([a7a03ea](https://github.com/brightcove/videojs-dock/commit/a7a03ea)) 50 | * Update to use plugin generator v7.0.2 ([a5ac66b](https://github.com/brightcove/videojs-dock/commit/a5ac66b)) 51 | * **package:** Update dependencies to enable Greenkeeper 🌴 ([#24](https://github.com/brightcove/videojs-dock/issues/24)) ([2b16991](https://github.com/brightcove/videojs-dock/commit/2b16991)) 52 | * **package:** update videojs-generate-karma-config to version 3.0.0 ([#25](https://github.com/brightcove/videojs-dock/issues/25)) ([9b88343](https://github.com/brightcove/videojs-dock/commit/9b88343)) 53 | * **package:** update videojs-generate-rollup-config to version 2.2.0 ([#28](https://github.com/brightcove/videojs-dock/issues/28)) ([a2703bc](https://github.com/brightcove/videojs-dock/commit/a2703bc)) 54 | 55 | 56 | ## [2.1.2](https://github.com/brightcove/videojs-dock/compare/v2.1.1...v2.1.2) (2017-05-19) 57 | 58 | ### Chores 59 | 60 | * Update tooling using generator v5 prerelease. ([#17](https://github.com/brightcove/videojs-dock/issues/17)) ([74b1e8e](https://github.com/brightcove/videojs-dock/commit/74b1e8e)) 61 | 62 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | We welcome contributions from everyone! 4 | 5 | ## Getting Started 6 | 7 | Make sure you have Node.js 4.8 or higher and npm installed. 8 | 9 | 1. Fork this repository and clone your fork 10 | 1. Install dependencies: `npm install` 11 | 1. Run a development server: `npm start` 12 | 13 | ### Making Changes 14 | 15 | Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship. 16 | 17 | When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository. 18 | 19 | ### Running Tests 20 | 21 | Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma]. 22 | 23 | - In all available and supported browsers: `npm test` 24 | - In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc. 25 | - While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local] 26 | 27 | 28 | [karma]: http://karma-runner.github.io/ 29 | [local]: http://localhost:9999/test/ 30 | [conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Brightcove, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # videojs-dock 2 | 3 | [![Build Status](https://travis-ci.org/brightcove/videojs-dock.svg?branch=master)](https://travis-ci.org/brightcove/videojs-dock) 4 | [![Greenkeeper badge](https://badges.greenkeeper.io/brightcove/videojs-dock.svg)](https://greenkeeper.io/) 5 | [![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com) 6 | 7 | [![NPM](https://nodei.co/npm/videojs-dock.png?downloads=true&downloadRank=true)](https://nodei.co/npm/videojs-dock/) 8 | 9 | A dock for videojs 10 | 11 | Maintenance Status: Stable 12 | 13 | 14 | 15 | 16 | 17 | 18 | - [Getting Started](#getting-started) 19 | - [Running Tests](#running-tests) 20 | - [Tag and Release](#tag-and-release) 21 | - [License](#license) 22 | 23 | 24 | 25 | ## Getting Started 26 | 27 | 1. Clone this repository! 28 | 1. Install dependencies: `npm install` 29 | 1. Run a development server: `npm start` 30 | 31 | That's it! Refer to the [video.js plugin standards](https://github.com/videojs/generator-videojs-plugin/docs/standards.md) for more detail. 32 | 33 | ### Running Tests 34 | 35 | - In all available and supported browsers: `npm test` 36 | - In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc. 37 | - While development server is running, navigate to [`http://localhost:9999/test/`](http://localhost:9999/test/) (_note:_ port may vary, check console output) 38 | 39 | ### Tag and Release 40 | 41 | 1. Make sure everything is committed. 42 | 1. `npm version *` where `*` is `major`, `minor`, `patch`, etc. [Read more about versioning.](https://github.com/videojs/generator-videojs-plugin/docs/standards.md#versioning) 43 | 1. `npm publish` 44 | 45 | ## License 46 | 47 | Apache-2.0. Copyright (c) Brightcove, Inc. 48 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 37 | 38 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "videojs-dock", 3 | "version": "3.0.0", 4 | "description": "Dock plugin for videojs", 5 | "main": "dist/videojs-dock.cjs.js", 6 | "keywords": [ 7 | "dock", 8 | "videojs", 9 | "videojs-plugin" 10 | ], 11 | "author": "Brightcove, Inc.", 12 | "license": "Apache-2.0", 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/brightcove/videojs-dock" 16 | }, 17 | "module": "dist/videojs-dock.es.js", 18 | "generator-videojs-plugin": { 19 | "version": "7.3.2" 20 | }, 21 | "scripts": { 22 | "prebuild": "npm run clean", 23 | "build": "npm-run-all -p build:*", 24 | "build:css": "node-sass src/plugin.scss dist/videojs-dock.css --output-style=compressed --linefeed=lf", 25 | "build:js": "rollup -c scripts/rollup.config.js", 26 | "clean": "shx rm -rf ./dist ./test/dist", 27 | "postclean": "shx mkdir -p ./dist ./test/dist", 28 | "docs": "doctoc README.md", 29 | "lint": "vjsstandard", 30 | "server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch", 31 | "start": "npm-run-all -p server watch", 32 | "pretest": "npm-run-all lint build", 33 | "test": "karma start scripts/karma.conf.js", 34 | "update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s", 35 | "preversion": "npm test", 36 | "version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md", 37 | "watch": "npm-run-all -p watch:*", 38 | "watch:css": "npm run build:css -- -w", 39 | "watch:js": "npm run build:js -- -w", 40 | "posttest": "shx cat test/dist/coverage/text.txt", 41 | "prepublishOnly": "npm run build && vjsverify --skip-es-check" 42 | }, 43 | "vjsstandard": { 44 | "ignore": [ 45 | "dist", 46 | "docs", 47 | "test/dist" 48 | ] 49 | }, 50 | "files": [ 51 | "CONTRIBUTING.md", 52 | "dist/", 53 | "docs/", 54 | "index.html", 55 | "scripts/", 56 | "src/", 57 | "test/" 58 | ], 59 | "dependencies": { 60 | "global": "^4.4.0", 61 | "video.js": "^7.17.0" 62 | }, 63 | "devDependencies": { 64 | "conventional-changelog-cli": "^2.1.1", 65 | "conventional-changelog-videojs": "^3.0.2", 66 | "doctoc": "^2.1.0", 67 | "husky": "^7.0.4", 68 | "karma": "^6.3.9", 69 | "lint-staged": "^12.1.2", 70 | "node-sass": "^7.0.0", 71 | "not-prerelease": "^1.0.1", 72 | "npm-merge-driver-install": "^2.0.2", 73 | "npm-run-all": "^4.1.5", 74 | "pkg-ok": "^2.3.1", 75 | "postcss-cli": "^9.1.0", 76 | "rollup": "^2.61.1", 77 | "shx": "^0.3.3", 78 | "sinon": "^12.0.1", 79 | "videojs-generate-karma-config": "^8.0.1", 80 | "videojs-generate-postcss-config": "^2.1.1", 81 | "videojs-generate-rollup-config": "^7.0.0", 82 | "videojs-generator-verify": "^4.0.1", 83 | "videojs-standard": "^9.0.1" 84 | }, 85 | "lint-staged": { 86 | "*.js": [ 87 | "vjsstandard --fix", 88 | "git add" 89 | ], 90 | "README.md": [ 91 | "npm run docs:toc", 92 | "git add" 93 | ] 94 | }, 95 | "husky": { 96 | "hooks": { 97 | "pre-commit": "lint-staged" 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brightcove/videojs-dock/8309e7f28bdced765ca0421b0326967e0c870172/poster.jpg -------------------------------------------------------------------------------- /scripts/karma.conf.js: -------------------------------------------------------------------------------- 1 | const generate = require('videojs-generate-karma-config'); 2 | 3 | module.exports = function(config) { 4 | 5 | // see https://github.com/videojs/videojs-generate-karma-config 6 | // for options 7 | const options = {}; 8 | 9 | config = generate(config, options); 10 | 11 | // any other custom stuff not supported by options here! 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /scripts/postcss.config.js: -------------------------------------------------------------------------------- 1 | const generate = require('videojs-generate-postcss-config'); 2 | 3 | module.exports = function(context) { 4 | const result = generate({}, context); 5 | 6 | // do custom stuff here 7 | 8 | return result; 9 | }; 10 | -------------------------------------------------------------------------------- /scripts/rollup.config.js: -------------------------------------------------------------------------------- 1 | const generate = require('videojs-generate-rollup-config'); 2 | 3 | // see https://github.com/videojs/videojs-generate-rollup-config 4 | // for options 5 | const options = {}; 6 | const config = generate(options); 7 | 8 | // Add additonal builds/customization here! 9 | 10 | // export the builds to rollup 11 | export default Object.values(config.builds); 12 | -------------------------------------------------------------------------------- /src/guid.js: -------------------------------------------------------------------------------- 1 | let guid = 1; 2 | const newGuid = function newGuid() { 3 | return guid++; 4 | }; 5 | 6 | export default newGuid; 7 | -------------------------------------------------------------------------------- /src/plugin.js: -------------------------------------------------------------------------------- 1 | import document from 'global/document'; 2 | import videojs from 'video.js'; 3 | import guid from './guid.js'; 4 | import {version as VERSION} from '../package.json'; 5 | 6 | const dom = videojs.dom || videojs; 7 | const registerPlugin = videojs.registerPlugin || videojs.plugin; 8 | const Component = videojs.getComponent('Component'); 9 | 10 | /** 11 | * Title Component 12 | */ 13 | export class Title extends Component { 14 | constructor(player, options) { 15 | super(player, options); 16 | 17 | const tech = player.$('.vjs-tech'); 18 | 19 | tech.setAttribute('aria-labelledby', this.title.id); 20 | tech.setAttribute('aria-describedby', this.description.id); 21 | } 22 | 23 | createEl() { 24 | const title = dom.createEl('div', { 25 | className: 'vjs-dock-title', 26 | title: this.options_.title, 27 | innerHTML: this.options_.title 28 | }, { 29 | id: `vjs-dock-title-${guid()}` 30 | }); 31 | const desc = dom.createEl('div', { 32 | className: 'vjs-dock-description', 33 | title: this.options_.description, 34 | innerHTML: this.options_.description 35 | }, { 36 | id: `vjs-dock-description-${guid()}` 37 | }); 38 | const el = super.createEl('div', { 39 | className: 'vjs-dock-text' 40 | }); 41 | 42 | this.title = title; 43 | this.description = desc; 44 | 45 | el.appendChild(title); 46 | el.appendChild(desc); 47 | return el; 48 | } 49 | 50 | update(title, description) { 51 | this.title.innerHTML = ''; 52 | this.description.innerHTML = ''; 53 | this.title.appendChild(document.createTextNode(title)); 54 | this.description.appendChild(document.createTextNode(description)); 55 | } 56 | } 57 | 58 | /** 59 | * Shelf Component 60 | */ 61 | export class Shelf extends Component { 62 | createEl() { 63 | return super.createEl('div', { 64 | className: 'vjs-dock-shelf' 65 | }); 66 | } 67 | } 68 | 69 | videojs.registerComponent('Title', Title); 70 | videojs.registerComponent('Shelf', Shelf); 71 | 72 | /** 73 | * A video.js plugin. 74 | * 75 | * In the plugin function, the value of `this` is a video.js `Player` 76 | * instance. You cannot rely on the player being in a "ready" state here, 77 | * depending on how the plugin is invoked. This may or may not be important 78 | * to you; if not, remove the wait for "ready"! 79 | * 80 | * @function dock 81 | * @param {Object} [options={}] 82 | * An object of options left to the plugin author to define. 83 | */ 84 | const dock = function(options) { 85 | const opts = options || {}; 86 | const settings = { 87 | title: { 88 | title: opts.title || '', 89 | description: opts.description || '' 90 | } 91 | }; 92 | 93 | let title = this.title; 94 | let shelf = this.shelf; 95 | 96 | this.addClass('vjs-dock'); 97 | 98 | // If dock is initalized as part of player options, the player won't be ready 99 | // and the dock items will be hidden by the poster image when it's created. 100 | // In those cases, wait for player ready. 101 | this.ready(() => { 102 | const bpbIndex = this.children().indexOf(this.getChild('bigPlayButton')); 103 | const index = bpbIndex > 0 ? bpbIndex - 1 : null; 104 | 105 | // add shelf first so `title` is added before it if available 106 | // because shelf will now be at index 107 | if (!shelf) { 108 | shelf = this.shelf = this.addChild('shelf', settings, index); 109 | } 110 | 111 | if (!title) { 112 | title = this.title = this.addChild('title', settings.title, index); 113 | } else { 114 | title.update(settings.title.title, settings.title.description); 115 | } 116 | 117 | this.one(title, 'dispose', function() { 118 | this.title = null; 119 | }); 120 | 121 | this.one(shelf, 'dispose', function() { 122 | this.shelf = null; 123 | }); 124 | 125 | // Update aria attributes to describe video content if title/description 126 | // IDs and text content are present. If unavailable, accessibility 127 | // landmark can fall back to generic `Video Player` aria-label. 128 | const titleEl = title.title; 129 | const descriptionEl = title.description; 130 | const titleId = titleEl.id; 131 | const descriptionId = descriptionEl.id; 132 | 133 | if (titleId && titleEl.textContent) { 134 | this.setAttribute('aria-labelledby', this.id() + ' ' + titleId); 135 | } 136 | 137 | if (descriptionId && descriptionEl.textContent) { 138 | this.setAttribute('aria-describedby', descriptionId); 139 | } 140 | }, true); 141 | }; 142 | 143 | dock.VERSION = VERSION; 144 | 145 | // Register the plugin with video.js. 146 | registerPlugin('dock', dock); 147 | 148 | export default dock; 149 | -------------------------------------------------------------------------------- /src/plugin.scss: -------------------------------------------------------------------------------- 1 | $browser-context: 16; 2 | 3 | @function em($pixels, $context: $browser-context) { 4 | @return #{$pixels/$context}em; 5 | } 6 | 7 | @mixin transition($string: $transition--default) { 8 | -webkit-transition: $string; 9 | -moz-transition: $string; 10 | -o-transition: $string; 11 | transition: $string; 12 | } 13 | 14 | .video-js { 15 | $shelf-width: 25%; 16 | 17 | .vjs-dock-text, 18 | .vjs-dock-shelf { 19 | font-size: em(18, 10); 20 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 21 | pointer-events: none; 22 | position: absolute; 23 | top: 0; 24 | @include transition(opacity 0.1s); 25 | } 26 | 27 | .vjs-dock-text { 28 | left: 0; 29 | margin: 0; 30 | width: 100%; 31 | 32 | // Adopt some core styles from .vjs-modal-dialog from video.js 33 | background: rgba(0, 0, 0, 0.8); 34 | background: -webkit-linear-gradient(to bottom, rgba(0,0,0,.8) 0%, rgba(0,0,0,.7) 30%, rgba(0,0,0,.7) 70%, rgba(0,0,0,0) 100%); 35 | background: linear-gradient(to bottom, rgba(0,0,0,.8) 0%, rgba(0,0,0,.7) 30%, rgba(0,0,0,.7) 70%, rgba(0,0,0,0) 100%); 36 | padding: 1em $shelf-width 2em 1em; 37 | } 38 | 39 | &.vjs-no-flex .vjs-dock-text { 40 | padding-bottom: 1em; 41 | } 42 | 43 | .vjs-dock-shelf { 44 | padding: 1em 1em; 45 | right: 0; 46 | text-align: right; 47 | width: $shelf-width; 48 | 49 | * { 50 | pointer-events: auto; 51 | } 52 | } 53 | 54 | .vjs-dock-title, 55 | .vjs-dock-description { 56 | margin: 0; 57 | overflow: hidden; 58 | text-overflow: ellipsis; 59 | white-space: nowrap; 60 | } 61 | 62 | .vjs-dock-title { 63 | font-weight: bold; 64 | letter-spacing: 1px; 65 | line-height: 1.333; // 20px 66 | margin-bottom: 0.333em; // 5px 67 | } 68 | 69 | .vjs-dock-description { 70 | font-weight: normal; 71 | line-height: 1.5; // 18px 72 | } 73 | } 74 | 75 | .vjs-playing.vjs-user-inactive .vjs-dock-text, 76 | .vjs-playing.vjs-user-inactive .vjs-dock-shelf { 77 | opacity: 0; 78 | @include transition(opacity 1s); 79 | } 80 | 81 | .vjs-playing.vjs-no-flex.vjs-user-inactive .vjs-dock-text, 82 | .vjs-playing.vjs-no-flex.vjs-user-inactive .vjs-dock-shelf { 83 | display: none; 84 | } 85 | -------------------------------------------------------------------------------- /test/plugin.test.js: -------------------------------------------------------------------------------- 1 | import document from 'global/document'; 2 | 3 | import QUnit from 'qunit'; 4 | import sinon from 'sinon'; 5 | import videojs from 'video.js'; 6 | 7 | import plugin from '../src/plugin'; 8 | 9 | const Player = videojs.getComponent('Player'); 10 | 11 | QUnit.test('the environment is sane', function(assert) { 12 | assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists'); 13 | assert.strictEqual(typeof sinon, 'object', 'sinon exists'); 14 | assert.strictEqual(typeof videojs, 'function', 'videojs exists'); 15 | assert.strictEqual(typeof plugin, 'function', 'plugin is a function'); 16 | }); 17 | 18 | QUnit.module('videojs-dock', { 19 | 20 | beforeEach() { 21 | this.fixture = document.getElementById('qunit-fixture'); 22 | this.video = document.createElement('video'); 23 | this.fixture.appendChild(this.video); 24 | this.player = videojs(this.video); 25 | 26 | // Mock the environment's timers because certain things - particularly 27 | // player readiness - are asynchronous in video.js 5. 28 | this.clock = sinon.useFakeTimers(); 29 | }, 30 | 31 | afterEach() { 32 | 33 | // The clock _must_ be restored before disposing the player; otherwise, 34 | // certain timeout listeners that happen inside video.js may throw errors. 35 | this.clock.restore(); 36 | this.player.dispose(); 37 | } 38 | }); 39 | 40 | QUnit.test('registers itself with video.js', function(assert) { 41 | assert.expect(2); 42 | 43 | assert.strictEqual( 44 | typeof Player.prototype.dock, 45 | 'function', 46 | 'videojs-dock plugin was registered' 47 | ); 48 | 49 | this.player.dock(); 50 | 51 | // Tick the clock forward enough to trigger the player to be "ready". 52 | this.clock.tick(1); 53 | 54 | assert.ok( 55 | this.player.hasClass('vjs-dock'), 56 | 'the plugin adds a class to the player' 57 | ); 58 | }); 59 | 60 | QUnit.test('adds aria attributes to the player when both title and description values are present in options', function(assert) { 61 | assert.expect(2); 62 | 63 | this.player.dock({ 64 | title: 'Test Title', 65 | description: 'Test description.' 66 | }); 67 | 68 | // Tick the clock forward enough to trigger the player to be "ready". 69 | this.clock.tick(1); 70 | 71 | const titleId = this.player.title.title.id; 72 | const descriptionId = this.player.title.description.id; 73 | 74 | assert.ok( 75 | this.player.getAttribute('aria-labelledby').includes(titleId), 76 | 'the plugin adds an aria-labelledby to the player based on title ID' 77 | ); 78 | 79 | assert.ok( 80 | this.player.getAttribute('aria-describedby').includes(descriptionId), 81 | 'the plugin adds an aria-describedby to the player based on description ID' 82 | ); 83 | }); 84 | 85 | QUnit.test('adds aria-labelledby attribute to the player when only title is passed through options', function(assert) { 86 | assert.expect(2); 87 | 88 | this.player.dock({ 89 | title: 'Test Title' 90 | }); 91 | 92 | // Tick the clock forward enough to trigger the player to be "ready". 93 | this.clock.tick(1); 94 | 95 | const titleId = this.player.title.title.id; 96 | 97 | assert.ok( 98 | this.player.getAttribute('aria-labelledby').includes(titleId), 99 | 'the plugin adds an aria-labelledby to the player based on title ID' 100 | ); 101 | 102 | assert.ok( 103 | this.player.getAttribute('aria-describedby') === null, 104 | 'the plugin does not add an empty aria-describedby to the player if description text is ""' 105 | ); 106 | }); 107 | 108 | QUnit.test('adds aria-describedby attribute to the player when only description is passed through options', function(assert) { 109 | assert.expect(2); 110 | 111 | this.player.dock({ 112 | description: 'Test description.' 113 | }); 114 | 115 | // Tick the clock forward enough to trigger the player to be "ready". 116 | this.clock.tick(1); 117 | 118 | const descriptionId = this.player.title.description.id; 119 | 120 | assert.ok( 121 | this.player.getAttribute('aria-describedby').includes(descriptionId), 122 | 'the plugin adds an aria-describedby to the player based on description ID' 123 | ); 124 | 125 | assert.ok( 126 | this.player.getAttribute('aria-labelledby') === null, 127 | 'the plugin does not add an empty aria-labelledby to the player if title text is ""' 128 | ); 129 | }); 130 | --------------------------------------------------------------------------------