Repository: videojs/videojs-contrib-quality-levels Branch: main Commit: 0452c163bc3f Files: 26 Total size: 45.2 KB Directory structure: gitextract_g3efd7_y/ ├── .editorconfig ├── .github/ │ ├── ISSUE_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .husky/ │ ├── pre-commit │ └── pre-push ├── .npmignore ├── .nvmrc ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── index.html ├── package.json ├── scripts/ │ ├── jsdoc.config.json │ ├── karma.conf.js │ └── rollup.config.js ├── src/ │ ├── plugin.js │ ├── quality-level-list.js │ └── quality-level.js ├── test/ │ ├── plugin.test.js │ ├── quality-level-list.test.js │ └── test-helpers.js └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # http://editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ## Description Briefly describe the issue. Include a [reduced test case](https://css-tricks.com/reduced-test-cases/). ## Steps to reproduce Explain in detail the exact steps necessary to reproduce the issue. 1. 2. 3. ## Results ### Expected Please describe what you expected to see. ### Actual Please describe what actually happened. ### Error output If there are any errors at all, please include them here. ## Additional Information Please include any additional information necessary here. Including the following: ### versions #### videojs what version of videojs does this occur with? #### browsers what browser are affected? #### OSes what platforms (operating systems and devices) are affected? ### plugins are any videojs plugins being used on the page? If so, please list them below. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Description Please describe the change as necessary. If it's a feature or enhancement please be as detailed as possible. If it's a bug fix, please link the issue that it fixes or describe the bug in as much detail. ## Specific Changes proposed Please list the specific changes involved in this pull request. ## Requirements Checklist - [ ] Feature implemented / Bug fixed - [ ] If necessary, more likely in a feature request than a bug fix - [ ] Unit Tests updated or fixed - [ ] Docs/guides updated - [ ] Reviewed by Two Core Contributors ================================================ FILE: .github/workflows/ci.yml ================================================ name: ci on: [push, pull_request] jobs: should-skip: continue-on-error: true runs-on: ubuntu-latest # Map a step output to a job output outputs: should-skip-job: ${{steps.skip-check.outputs.should_skip}} steps: - id: skip-check uses: fkirc/skip-duplicate-actions@v5.3.0 with: github_token: ${{github.token}} ci: needs: should-skip if: ${{needs.should-skip.outputs.should-skip-job != 'true' || github.ref == 'refs/heads/main'}} strategy: fail-fast: false matrix: os: [ubuntu-latest] test-type: ['unit', 'coverage'] env: BROWSER_STACK_USERNAME: ${{secrets.BROWSER_STACK_USERNAME}} BROWSER_STACK_ACCESS_KEY: ${{secrets.BROWSER_STACK_ACCESS_KEY}} CI_TEST_TYPE: ${{matrix.test-type}} runs-on: ${{matrix.os}} steps: - name: checkout code uses: actions/checkout@v3 - name: read node version from .nvmrc run: echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_OUTPUT shell: bash id: nvm - name: update apt cache on linux w/o browserstack run: sudo apt-get update - name: install ffmpeg/pulseaudio for firefox on linux w/o browserstack run: sudo apt-get install ffmpeg pulseaudio - name: start pulseaudio for firefox on linux w/o browserstack run: pulseaudio -D - name: setup node uses: actions/setup-node@v3 with: node-version: '${{steps.nvm.outputs.NVMRC}}' cache: npm # turn off the default setup-node problem watchers... - run: echo "::remove-matcher owner=eslint-compact::" - run: echo "::remove-matcher owner=eslint-stylish::" - run: echo "::remove-matcher owner=tsc::" - name: npm install run: npm i --prefer-offline --no-audit - name: run npm test uses: coactions/setup-xvfb@v1 with: run: npm run test - name: coverage uses: codecov/codecov-action@v3 with: token: ${{secrets.CODECOV_TOKEN}} files: './test/dist/coverage/coverage-final.json' fail_ci_if_error: true if: ${{startsWith(env.CI_TEST_TYPE, 'coverage')}} ================================================ FILE: .gitignore ================================================ # OS Thumbs.db ehthumbs.db Desktop.ini .DS_Store ._* # Editors *~ *.swp *.tmproj *.tmproject *.sublime-* .idea/ .project/ .settings/ .vscode/ # Logs logs *.log npm-debug.log* # Dependency directories bower_components/ node_modules/ # Build-related directories dist/ es/ cjs/ docs/api/ test/dist/ .eslintcache .yo-rc.json ================================================ FILE: .husky/pre-commit ================================================ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npx lint-staged ================================================ FILE: .husky/pre-push ================================================ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npm run test ================================================ FILE: .npmignore ================================================ # Intentionally left blank, so that npm does not ignore anything by default, # but relies on the package.json "files" array to explicitly define what ends # up in the package. ================================================ FILE: .nvmrc ================================================ 16 ================================================ FILE: .travis.yml ================================================ sudo: false dist: trusty language: node_js # node version is specified using the .nvmrc file before_install: - npm install -g greenkeeper-lockfile@1 before_script: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start - greenkeeper-lockfile-update after_script: - greenkeeper-lockfile-upload addons: firefox: latest chrome: stable ================================================ FILE: CHANGELOG.md ================================================ # [4.1.0](https://github.com/videojs/videojs-contrib-quality-levels/compare/v4.0.0...v4.1.0) (2024-03-06) ### Features * add types support (#149) ([7bc330e](https://github.com/videojs/videojs-contrib-quality-levels/commit/7bc330e)), closes [#149](https://github.com/videojs/videojs-contrib-quality-levels/issues/149) ### Chores * Update CI workflow (#144) ([f088ede](https://github.com/videojs/videojs-contrib-quality-levels/commit/f088ede)), closes [#144](https://github.com/videojs/videojs-contrib-quality-levels/issues/144) # [4.0.0](https://github.com/videojs/videojs-contrib-quality-levels/compare/v3.0.0...v4.0.0) (2023-03-31) ### Features * make quality level list iterable (#136) ([c054f8c](https://github.com/videojs/videojs-contrib-quality-levels/commit/c054f8c)), closes [#136](https://github.com/videojs/videojs-contrib-quality-levels/issues/136) * update to support only Video.js 8 and eliminate deprecation warnings (#138) ([ccab6ca](https://github.com/videojs/videojs-contrib-quality-levels/commit/ccab6ca)), closes [#138](https://github.com/videojs/videojs-contrib-quality-levels/issues/138) ### BREAKING CHANGES * This breaks compatibility with all versions of Internet Explorer. * With this change, videojs-contrib-quality-levels supports only Video.js 8 and newer. # [3.0.0](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.2.1...v3.0.0) (2022-12-22) ### Features * Don't transpile classes ([7b01bb3](https://github.com/videojs/videojs-contrib-quality-levels/commit/7b01bb3)) ### Chores * skip vjsverify es check ([89460b1](https://github.com/videojs/videojs-contrib-quality-levels/commit/89460b1)) ## [2.2.1](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.2.0...v2.2.1) (2022-11-23) ### Chores * do not run tests on npm version (#141) ([e598158](https://github.com/videojs/videojs-contrib-quality-levels/commit/e598158)), closes [#141](https://github.com/videojs/videojs-contrib-quality-levels/issues/141) * **package:** add Video.js 8 as a compatible version (#140) ([5e61e71](https://github.com/videojs/videojs-contrib-quality-levels/commit/5e61e71)), closes [#140](https://github.com/videojs/videojs-contrib-quality-levels/issues/140) # [2.2.0](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.1.0...v2.2.0) (2022-09-09) ### Features * add frameRate property to the quality level (#134) ([13998a7](https://github.com/videojs/videojs-contrib-quality-levels/commit/13998a7)), closes [#134](https://github.com/videojs/videojs-contrib-quality-levels/issues/134) ### Chores * update jsdoc (#132) ([dbcc7b4](https://github.com/videojs/videojs-contrib-quality-levels/commit/dbcc7b4)), closes [#132](https://github.com/videojs/videojs-contrib-quality-levels/issues/132) ### Code Refactoring * remove IE8 specific changes (#133) ([316f405](https://github.com/videojs/videojs-contrib-quality-levels/commit/316f405)), closes [#133](https://github.com/videojs/videojs-contrib-quality-levels/issues/133) ### Documentation * Fix typo in README (#135) ([7036132](https://github.com/videojs/videojs-contrib-quality-levels/commit/7036132)), closes [#135](https://github.com/videojs/videojs-contrib-quality-levels/issues/135) ### Tests * update karma-config to fix local tests (#137) ([77bb0f1](https://github.com/videojs/videojs-contrib-quality-levels/commit/77bb0f1)), closes [#137](https://github.com/videojs/videojs-contrib-quality-levels/issues/137) # [2.1.0](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.0.9...v2.1.0) (2021-04-05) ### Features * mark Video.js as a peer dependency (#125) ([1115f78](https://github.com/videojs/videojs-contrib-quality-levels/commit/1115f78)), closes [#125](https://github.com/videojs/videojs-contrib-quality-levels/issues/125) ### Chores * **package:** update npm-run-all to 4.1.5 (#72) ([a9e7ff5](https://github.com/videojs/videojs-contrib-quality-levels/commit/a9e7ff5)), closes [#72](https://github.com/videojs/videojs-contrib-quality-levels/issues/72) * **package:** update videojs-generate-karma-config to version 5.0.2 (#77) ([72190a4](https://github.com/videojs/videojs-contrib-quality-levels/commit/72190a4)), closes [#77](https://github.com/videojs/videojs-contrib-quality-levels/issues/77) * Update videojs-generate-karma-config to the latest version 🚀 (#65) ([50b2b42](https://github.com/videojs/videojs-contrib-quality-levels/commit/50b2b42)), closes [#65](https://github.com/videojs/videojs-contrib-quality-levels/issues/65) ### Documentation * Fixed grammar and removed some unnecessary words (#83) ([63da16f](https://github.com/videojs/videojs-contrib-quality-levels/commit/63da16f)), closes [#83](https://github.com/videojs/videojs-contrib-quality-levels/issues/83) * **README:** Fix minor typo (#114) ([153583e](https://github.com/videojs/videojs-contrib-quality-levels/commit/153583e)), closes [#114](https://github.com/videojs/videojs-contrib-quality-levels/issues/114) * update description in readme (#84) ([433df96](https://github.com/videojs/videojs-contrib-quality-levels/commit/433df96)), closes [#84](https://github.com/videojs/videojs-contrib-quality-levels/issues/84) ## [2.0.9](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.0.8...v2.0.9) (2018-09-17) ### Bug Fixes * another version reporting issue ([9003e8d](https://github.com/videojs/videojs-contrib-quality-levels/commit/9003e8d)) ## [2.0.8](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.0.7...v2.0.8) (2018-09-17) ### Bug Fixes * Remove the postinstall script to prevent install issues (#54) ([7562cdb](https://github.com/videojs/videojs-contrib-quality-levels/commit/7562cdb)), closes [#54](https://github.com/videojs/videojs-contrib-quality-levels/issues/54) * report correct version (#57) ([1992300](https://github.com/videojs/videojs-contrib-quality-levels/commit/1992300)), closes [#57](https://github.com/videojs/videojs-contrib-quality-levels/issues/57) ### Chores * update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([9660214](https://github.com/videojs/videojs-contrib-quality-levels/commit/9660214)) * **package:** update rollup to version 0.66.0 (#56) ([0467b62](https://github.com/videojs/videojs-contrib-quality-levels/commit/0467b62)), closes [#56](https://github.com/videojs/videojs-contrib-quality-levels/issues/56) * **package:** update videojs-contrib-hls to version 5.14.1 (#31) ([b1a17fa](https://github.com/videojs/videojs-contrib-quality-levels/commit/b1a17fa)), closes [#31](https://github.com/videojs/videojs-contrib-quality-levels/issues/31) * **package:** update videojs-generate-rollup-config to version 2.2.0 (#55) ([4ad0a93](https://github.com/videojs/videojs-contrib-quality-levels/commit/4ad0a93)), closes [#55](https://github.com/videojs/videojs-contrib-quality-levels/issues/55) ## [2.0.7](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.0.6...v2.0.7) (2018-08-23) ### Chores * generator v7 (#50) ([7837d93](https://github.com/videojs/videojs-contrib-quality-levels/commit/7837d93)), closes [#50](https://github.com/videojs/videojs-contrib-quality-levels/issues/50) ## [2.0.6](https://github.com/videojs/videojs-contrib-quality-levels/compare/v2.0.5...v2.0.6) (2018-08-03) ### Bug Fixes * babel the es dist, by updating the generator (#45) ([0123ee8](https://github.com/videojs/videojs-contrib-quality-levels/commit/0123ee8)), closes [#45](https://github.com/videojs/videojs-contrib-quality-levels/issues/45) ## 2.0.5 (2018-07-05) ### Chores * video.js 5/6 compatibility and travis update (#12) ([c69ac5d](https://github.com/videojs/videojs-contrib-quality-levels/commit/c69ac5d)), closes [#12](https://github.com/videojs/videojs-contrib-quality-levels/issues/12) ## 2.0.4 (2018-01-22) * Allow video js 6 to be used (#25) ## 2.0.3 (2017-02-09) * chore: video.js 5/6 compatibility and travis update (#12) ## 2.0.2 (2016-12-23) * Make global a dependency instead of devDependency ## 2.0.1 (2016-12-13) * Make browserify-versionify a dependency instead of devDependency ## 2.0.0 (2016-12-12) * Remove HLS and Dash specific logic * Return QualityLevel added or removed when using the add or remove api ================================================ FILE: CONTRIBUTING.md ================================================ # CONTRIBUTING We welcome contributions from everyone! ## Getting Started Make sure you have Node.js 8 or higher and npm installed. 1. Fork this repository and clone your fork 1. Install dependencies: `npm install` 1. Run a development server: `npm start` ### Making Changes Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship. When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository. ### Running Tests 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]. - In all available and supported browsers: `npm test` - In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc. - While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local] [karma]: http://karma-runner.github.io/ [local]: http://localhost:9999/test/ [conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md ================================================ FILE: LICENSE ================================================ Copyright Brightcove, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # videojs-contrib-quality-levels [![Build Status](https://travis-ci.org/videojs/videojs-contrib-quality-levels.svg?branch=master)](https://travis-ci.org/videojs/videojs-contrib-quality-levels) [![Greenkeeper badge](https://badges.greenkeeper.io/videojs/videojs-contrib-quality-levels.svg)](https://greenkeeper.io/) [![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com) [![NPM](https://nodei.co/npm/videojs-contrib-quality-levels.png?downloads=true&downloadRank=true)](https://nodei.co/npm/videojs-contrib-quality-levels/) A plugin that provides a framework of working with source quality levels. Maintenance Status: Stable - [Installation](#installation) - [Using](#using) - [Supporting Quality Levels for your source](#supporting-quality-levels-for-your-source) - [Populating the list](#populating-the-list) - [Triggering the 'change' event](#triggering-the-change-event) - [Supported Projects](#supported-projects) - [Including the Plugin](#including-the-plugin) - [` ``` ### Browserify When using with Browserify, install videojs-contrib-quality-levels via npm and `require` the plugin as you would any other module. ```js var videojs = require('video.js'); // The actual plugin function is exported by this module, but it is also // attached to the `Player.prototype`; so, there is no need to assign it // to a variable. require('videojs-contrib-quality-levels'); var player = videojs('my-video'); player.qualityLevels(); ``` ### RequireJS/AMD When using with RequireJS (or another AMD library), get the script in whatever way you prefer and `require` the plugin as you normally would: ```js require(['video.js', 'videojs-contrib-quality-levels'], function(videojs) { var player = videojs('my-video'); player.qualityLevels(); }); ``` ## License Apache-2.0. Copyright (c) Brightcove, Inc. [videojs]: http://videojs.com/ ================================================ FILE: index.html ================================================ videojs-contrib-quality-levels Demo

Quality Levels:

================================================ FILE: package.json ================================================ { "name": "videojs-contrib-quality-levels", "version": "4.1.0", "description": "Exposes a list of quality levels available for the source.", "main": "dist/videojs-contrib-quality-levels.cjs.js", "types": "dist/types/plugin.d.ts", "jsnext:main": "src/plugin.js", "generator-videojs-plugin": { "version": "8.0.0" }, "repository": "videojs/videojs-contrib-quality-levels", "scripts": { "prebuild": "npm run clean", "build": "npm-run-all -s clean -p build:*", "build-prod": "cross-env-shell NO_TEST_BUNDLE=1 'npm run build'", "build-test": "cross-env-shell TEST_BUNDLE_ONLY=1 'npm run build'", "build:js": "rollup -c scripts/rollup.config.js", "build:types": "tsc", "clean": "shx rm -rf ./dist ./test/dist ./cjs ./es && shx mkdir -p ./dist ./test/dist ./cjs ./es", "postclean": "shx mkdir -p ./dist ./test/dist", "docs": "npm-run-all docs:*", "docs:api": "jsdoc src -c scripts/jsdoc.config.json -r -d docs/api", "docs:toc": "doctoc --notitle README.md", "lint": "vjsstandard", "server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch", "start": "npm-run-all -p server watch", "pretest": "npm-run-all lint build", "test": "npm-run-all lint build-test && karma start scripts/karma.conf.js", "posttest": "shx cat test/dist/coverage/text.txt", "update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s", "preversion": "npm test", "version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md", "watch": "npm-run-all -p watch:*", "watch:js": "npm run build:js -- -w", "prepublishOnly": "npm-run-all build-prod && vjsverify --verbose --skip-es-check", "prepare": "husky install" }, "keywords": [ "videojs", "videojs-plugin" ], "author": "Brightcove, Inc.", "license": "Apache-2.0", "copyright": "Copyright Brightcove, Inc. ", "videojs-plugin": { "script": "dist/videojs-contrib-quality-levels.min.js" }, "vjsstandard": { "ignore": [ "cjs", "dist", "docs", "ejs", "test/dist" ] }, "files": [ "CONTRIBUTING.md", "dist/", "docs/", "index.html", "scripts/", "src/", "test/" ], "dependencies": { "global": "^4.4.0" }, "peerDependencies": { "video.js": "^8" }, "devDependencies": { "@babel/cli": "^7.13.16", "@babel/runtime": "^7.14.0", "@videojs/babel-config": "^0.2.0", "@videojs/generator-helpers": "~2.0.2", "conventional-changelog-cli": "^2.0.1", "conventional-changelog-videojs": "^3.0.0", "doctoc": "^1.3.1", "husky": "^8.0.3", "jsdoc": "^3.6.11", "karma": "^6.3.2", "lint-staged": "^7.2.2", "not-prerelease": "^1.0.1", "npm-merge-driver-install": "^1.0.0", "npm-run-all": "^4.1.5", "pkg-ok": "^2.2.0", "rollup": "^2.46.0", "semver": "^5.1.0", "shx": "^0.3.2", "sinon": "^9.1.0", "typescript": "^5.4.2", "video.js": "^8", "videojs-generate-karma-config": "~8.0.0", "videojs-generate-rollup-config": "^7.0.0", "videojs-generator-verify": "^4.1.0", "videojs-standard": "^9.0.1" }, "module": "dist/videojs-contrib-quality-levels.es.js", "lint-staged": { "*.js": "vjsstandard --fix", "README.md": "doctoc --notitle" }, "browser": "dist/videojs-contrib-quality-levels.js", "engines": { "node": ">=16", "npm": ">=8" } } ================================================ FILE: scripts/jsdoc.config.json ================================================ { "plugins": ["plugins/markdown"] } ================================================ FILE: scripts/karma.conf.js ================================================ const generate = require('videojs-generate-karma-config'); module.exports = function(config) { // see https://github.com/videojs/videojs-generate-karma-config // for options const options = {}; config = generate(config, options); // any other custom stuff not supported by options here! }; ================================================ FILE: scripts/rollup.config.js ================================================ const generate = require('videojs-generate-rollup-config'); // see https://github.com/videojs/videojs-generate-rollup-config // for options const options = {}; const config = generate(options); // Add additonal builds/customization here! // export the builds to rollup export default Object.values(config.builds); ================================================ FILE: src/plugin.js ================================================ import videojs from 'video.js'; import QualityLevelList from './quality-level-list.js'; import {version as VERSION} from '../package.json'; /** * Initialization function for the qualityLevels plugin. Sets up the QualityLevelList and * event handlers. * * @param {Player} player Player object. * @param {Object} options Plugin options object. * @return {QualityLevelList} a list of QualityLevels */ const initPlugin = function(player, options) { const originalPluginFn = player.qualityLevels; const qualityLevelList = new QualityLevelList(); const disposeHandler = function() { qualityLevelList.dispose(); player.qualityLevels = originalPluginFn; player.off('dispose', disposeHandler); }; player.on('dispose', disposeHandler); player.qualityLevels = () => qualityLevelList; player.qualityLevels.VERSION = VERSION; return qualityLevelList; }; /** * A video.js plugin. * * In the plugin function, the value of `this` is a video.js `Player` * instance. You cannot rely on the player being in a "ready" state here, * depending on how the plugin is invoked. This may or may not be important * to you; if not, remove the wait for "ready"! * * @param {Object} options Plugin options object * @return {QualityLevelList} a list of QualityLevels */ const qualityLevels = function(options) { return initPlugin(this, videojs.obj.merge({}, options)); }; // Register the plugin with video.js. videojs.registerPlugin('qualityLevels', qualityLevels); // Include the version number. qualityLevels.VERSION = VERSION; export default qualityLevels; ================================================ FILE: src/quality-level-list.js ================================================ import videojs from 'video.js'; import QualityLevel from './quality-level.js'; /** * A list of QualityLevels. * * interface QualityLevelList : EventTarget { * getter QualityLevel (unsigned long index); * readonly attribute unsigned long length; * readonly attribute long selectedIndex; * * void addQualityLevel(QualityLevel qualityLevel) * void removeQualityLevel(QualityLevel remove) * QualityLevel? getQualityLevelById(DOMString id); * * attribute EventHandler onchange; * attribute EventHandler onaddqualitylevel; * attribute EventHandler onremovequalitylevel; * }; * * @extends videojs.EventTarget * @class QualityLevelList */ class QualityLevelList extends videojs.EventTarget { /** * Creates a QualityLevelList. */ constructor() { super(); let list = this; // eslint-disable-line list.levels_ = []; list.selectedIndex_ = -1; /** * Get the index of the currently selected QualityLevel. * * @returns {number} The index of the selected QualityLevel. -1 if none selected. * @readonly */ Object.defineProperty(list, 'selectedIndex', { get() { return list.selectedIndex_; } }); /** * Get the length of the list of QualityLevels. * * @returns {number} The length of the list. * @readonly */ Object.defineProperty(list, 'length', { get() { return list.levels_.length; } }); list[Symbol.iterator] = () => list.levels_.values(); return list; } /** * Adds a quality level to the list. * * @param {Representation|Object} representation The representation of the quality level * @param {string} representation.id Unique id of the QualityLevel * @param {number=} representation.width Resolution width of the QualityLevel * @param {number=} representation.height Resolution height of the QualityLevel * @param {number} representation.bandwidth Bitrate of the QualityLevel * @param {number=} representation.frameRate Frame-rate of the QualityLevel * @param {Function} representation.enabled Callback to enable/disable QualityLevel * @return {QualityLevel} the QualityLevel added to the list * @method addQualityLevel */ addQualityLevel(representation) { let qualityLevel = this.getQualityLevelById(representation.id); // Do not add duplicate quality levels if (qualityLevel) { return qualityLevel; } const index = this.levels_.length; qualityLevel = new QualityLevel(representation); if (!('' + index in this)) { Object.defineProperty(this, index, { get() { return this.levels_[index]; } }); } this.levels_.push(qualityLevel); this.trigger({ qualityLevel, type: 'addqualitylevel' }); return qualityLevel; } /** * Removes a quality level from the list. * * @param {QualityLevel} qualityLevel The QualityLevel to remove from the list. * @return {QualityLevel|null} the QualityLevel removed or null if nothing removed * @method removeQualityLevel */ removeQualityLevel(qualityLevel) { let removed = null; for (let i = 0, l = this.length; i < l; i++) { if (this[i] === qualityLevel) { removed = this.levels_.splice(i, 1)[0]; if (this.selectedIndex_ === i) { this.selectedIndex_ = -1; } else if (this.selectedIndex_ > i) { this.selectedIndex_--; } break; } } if (removed) { this.trigger({ qualityLevel, type: 'removequalitylevel' }); } return removed; } /** * Searches for a QualityLevel with the given id. * * @param {string} id The id of the QualityLevel to find. * @return {QualityLevel|null} The QualityLevel with id, or null if not found. * @method getQualityLevelById */ getQualityLevelById(id) { for (let i = 0, l = this.length; i < l; i++) { const level = this[i]; if (level.id === id) { return level; } } return null; } /** * Resets the list of QualityLevels to empty * * @method dispose */ dispose() { this.selectedIndex_ = -1; this.levels_.length = 0; } } /** * change - The selected QualityLevel has changed. * addqualitylevel - A QualityLevel has been added to the QualityLevelList. * removequalitylevel - A QualityLevel has been removed from the QualityLevelList. */ QualityLevelList.prototype.allowedEvents_ = { change: 'change', addqualitylevel: 'addqualitylevel', removequalitylevel: 'removequalitylevel' }; // emulate attribute EventHandler support to allow for feature detection for (const event in QualityLevelList.prototype.allowedEvents_) { QualityLevelList.prototype['on' + event] = null; } export default QualityLevelList; ================================================ FILE: src/quality-level.js ================================================ /** * A single QualityLevel. * * interface QualityLevel { * readonly attribute DOMString id; * attribute DOMString label; * readonly attribute long width; * readonly attribute long height; * readonly attribute long bitrate; * attribute boolean enabled; * }; * * @class QualityLevel */ export default class QualityLevel { /** * Creates a QualityLevel * * @param {Representation|Object} representation The representation of the quality level * @param {string} representation.id Unique id of the QualityLevel * @param {number=} representation.width Resolution width of the QualityLevel * @param {number=} representation.height Resolution height of the QualityLevel * @param {number} representation.bandwidth Bitrate of the QualityLevel * @param {number=} representation.frameRate Frame-rate of the QualityLevel * @param {Function} representation.enabled Callback to enable/disable QualityLevel */ constructor(representation) { let level = this; // eslint-disable-line level.id = representation.id; level.label = level.id; level.width = representation.width; level.height = representation.height; level.bitrate = representation.bandwidth; level.frameRate = representation.frameRate; level.enabled_ = representation.enabled; Object.defineProperty(level, 'enabled', { /** * Get whether the QualityLevel is enabled. * * @return {boolean} True if the QualityLevel is enabled. */ get() { return level.enabled_(); }, /** * Enable or disable the QualityLevel. * * @param {boolean} enable true to enable QualityLevel, false to disable. */ set(enable) { level.enabled_(enable); } }); return level; } } ================================================ FILE: test/plugin.test.js ================================================ import document from 'global/document'; import QUnit from 'qunit'; import sinon from 'sinon'; import videojs from 'video.js'; import plugin from '../src/plugin'; const Player = videojs.getComponent('Player'); QUnit.test('the environment is sane', function(assert) { assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists'); assert.strictEqual(typeof sinon, 'object', 'sinon exists'); assert.strictEqual(typeof videojs, 'function', 'videojs exists'); assert.strictEqual(typeof plugin, 'function', 'plugin is a function'); }); QUnit.module('videojs-contrib-quality-levels', { beforeEach() { // Mock the environment's timers because certain things - particularly // player readiness - are asynchronous in video.js 5. This MUST come // before any player is created; otherwise, timers could get created // with the actual timer methods! this.clock = sinon.useFakeTimers(); this.fixture = document.getElementById('qunit-fixture'); this.video = document.createElement('video'); this.fixture.appendChild(this.video); this.player = videojs(this.video); }, afterEach() { this.player.dispose(); this.clock.restore(); } }); QUnit.test('registers itself with video.js', function(assert) { assert.strictEqual( typeof Player.prototype.qualityLevels, 'function', 'videojs-contrib-quality-levels plugin was registered' ); }); QUnit.test('player qualityLevels method returns the proper object', function(assert) { const qualityLevels = this.player.qualityLevels(); assert.equal( qualityLevels.length, 0, 'the returned object contained the length property with the proper value' ); assert.equal( qualityLevels.selectedIndex, -1, 'the returned object contained the selectedIndex property with the proper value' ); }); ================================================ FILE: test/quality-level-list.test.js ================================================ import QUnit from 'qunit'; import QualityLevelList from '../src/quality-level-list'; import { representations } from './test-helpers'; QUnit.module('QualityLevelList', { beforeEach() { this.qualityLevels = new QualityLevelList(); this.levels = representations; } }); QUnit.test('the QualityLevelList is iterable', function(assert) { assert.ok(Symbol.iterator in this.qualityLevels, 'is iterable'); }); QUnit.test('Properly adds QualityLevels to the QualityLevelList', function(assert) { let addCount = 0; this.qualityLevels.on('addqualitylevel', (event) => { addCount++; }); const expected0 = this.qualityLevels.addQualityLevel(this.levels[0]); assert.equal(this.qualityLevels.length, 1, 'added quality level'); assert.equal(addCount, 1, 'emmitted addqualitylevel event'); assert.strictEqual(this.qualityLevels[0], expected0, 'can access quality level with index'); const expected1 = this.qualityLevels.addQualityLevel(this.levels[1]); assert.equal(this.qualityLevels.length, 2, 'added quality level'); assert.equal(addCount, 2, 'emmitted addqualitylevel event'); assert.strictEqual(this.qualityLevels[1], expected1, 'can access quality level with index'); const expectedDuplicate = this.qualityLevels.addQualityLevel(this.levels[0]); assert.equal(this.qualityLevels.length, 2, 'does not add duplicate quality level'); assert.equal(addCount, 2, 'no event emitted on dulicate'); assert.strictEqual(this.qualityLevels[3], undefined, 'no index property defined'); assert.strictEqual(this.qualityLevels[0], expected0, 'quality level unchanged'); assert.strictEqual(this.qualityLevels[0], expectedDuplicate, 'adding duplicate returns same reference'); assert.strictEqual(this.qualityLevels[1], expected1, 'quality level unchanged'); }); QUnit.test('Properly removes QualityLevels from the QualityLevelList', function(assert) { let removeCount = 0; const expected = []; this.levels.forEach((qualityLevel) => { expected.push(this.qualityLevels.addQualityLevel(qualityLevel)); }); this.qualityLevels.on('removequalitylevel', (event) => { removeCount++; }); // Mock an initial selected quality level this.qualityLevels.selectedIndex_ = 2; assert.equal(this.qualityLevels.length, 4, '4 initial quality levels'); let removed = this.qualityLevels.removeQualityLevel(expected[3]); assert.equal(this.qualityLevels.length, 3, 'removed quality level'); assert.equal(removeCount, 1, 'emitted removequalitylevel event'); assert.strictEqual(removed, expected[3], 'returned removed level'); assert.notStrictEqual(this.qualityLevels[3], expected[3], 'nothing at index'); removed = this.qualityLevels.removeQualityLevel(expected[1]); assert.equal(this.qualityLevels.length, 2, 'removed quality level'); assert.equal(removeCount, 2, 'emitted removequalitylevel event'); assert.strictEqual(removed, expected[1], 'returned removed level'); assert.notStrictEqual(this.qualityLevels[1], expected[1], 'quality level not at index'); assert.strictEqual( this.qualityLevels[this.qualityLevels.selectedIndex], expected[2], 'selected index properly adjusted on quality level removal' ); removed = this.qualityLevels.removeQualityLevel(expected[3]); assert.equal(this.qualityLevels.length, 2, 'no quality level removed if not found'); assert.equal(removed, null, 'returned null when nothing removed'); assert.equal(removeCount, 2, 'no event emitted when quality level not found'); removed = this.qualityLevels.removeQualityLevel(expected[2]); assert.equal(this.qualityLevels.length, 1, 'quality level removed'); assert.equal(removeCount, 3, 'emitted removequalitylevel event'); assert.strictEqual(removed, expected[2], 'returned removed level'); assert.equal(this.qualityLevels.selectedIndex, -1, 'selectedIndex set to -1 when removing selected quality level'); }); QUnit.test('can get quality level by id', function(assert) { const expected = []; this.levels.forEach((qualityLevel) => { expected.push(this.qualityLevels.addQualityLevel(qualityLevel)); }); assert.strictEqual( this.qualityLevels.getQualityLevelById('0'), expected[0], 'found quality level with id "0"' ); assert.strictEqual( this.qualityLevels.getQualityLevelById('1'), expected[1], 'found quality level with id "1"' ); assert.strictEqual( this.qualityLevels.getQualityLevelById('2'), expected[2], 'found quality level with id "2"' ); assert.strictEqual( this.qualityLevels.getQualityLevelById('3'), expected[3], 'found quality level with id "3"' ); assert.strictEqual( this.qualityLevels.getQualityLevelById('4'), null, 'no quality level with id "4" found' ); }); ================================================ FILE: test/test-helpers.js ================================================ export const representations = [ { id: '0', width: 100, height: 100, bandwidth: 100, frameRate: 29.956, enabled() { return true; } }, { id: '1', width: 200, height: 200, bandwidth: 200, frameRate: 29.956, enabled() { return true; } }, { id: '2', width: 300, height: 300, bandwidth: 300, frameRate: 30, enabled() { return true; } }, { id: '3', width: 400, height: 400, bandwidth: 400, frameRate: 60, enabled() { return true; } } ]; ================================================ FILE: tsconfig.json ================================================ { "include": ["src/**/*"], "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "declaration": true, "emitDeclarationOnly": true, "outDir": "dist/types", "declarationMap": true, "skipLibCheck": true, "checkJs": false, "preserveWatchOutput": true } }