├── .babelrc
├── .eslintrc
├── .gitattributes
├── .gitignore
├── .stylelintrc
├── Gruntfile.js
├── README.md
├── RELEASE.md
├── changelog.md
├── demo
├── a11y.html
├── airplay.html
├── chromecast.html
├── demo.css
├── end.html
├── favicon.ico
├── index.html
├── markers.html
├── markersrolls.html
├── mediaelement.vtt
├── mejs-a11y-icons.svg
├── mejs-controls.svg
├── mejs-jump-forward.svg
├── mejs-quality.svg
├── mejs-skip-back.svg
├── multiple1.html
├── multiple2.html
├── playlist.html
├── postroll.html
├── preview.html
├── quality.html
├── speed.html
├── vast_sample.xml
└── vrview.html
├── dist
├── a11y
│ ├── a11y-i18n.js
│ ├── a11y.css
│ ├── a11y.js
│ ├── a11y.min.css
│ ├── a11y.min.js
│ ├── audio-description-icon.svg
│ └── video-description-icon.svg
├── ads-vast-vpaid
│ ├── ads-vast-vpaid.js
│ └── ads-vast-vpaid.min.js
├── ads
│ ├── ads-i18n.js
│ ├── ads.css
│ ├── ads.js
│ ├── ads.min.css
│ └── ads.min.js
├── airplay
│ ├── airplay.css
│ ├── airplay.js
│ ├── airplay.min.css
│ ├── airplay.min.js
│ ├── airplay.png
│ └── airplay.svg
├── chromecast
│ ├── chromecast-i18n.js
│ ├── chromecast.css
│ ├── chromecast.js
│ ├── chromecast.min.css
│ ├── chromecast.min.js
│ ├── chromecast.png
│ └── chromecast.svg
├── context-menu
│ ├── context-menu-i18n.js
│ ├── context-menu.css
│ ├── context-menu.js
│ ├── context-menu.min.css
│ └── context-menu.min.js
├── facebook-pixel
│ ├── facebook-pixel.js
│ └── facebook-pixel.min.js
├── google-analytics
│ ├── google-analytics.js
│ └── google-analytics.min.js
├── google-tag-manager
│ ├── google-tag-manager.js
│ └── google-tag-manager.min.js
├── jump-forward
│ ├── jump-forward-i18n.js
│ ├── jump-forward.js
│ ├── jump-forward.min.js
│ └── jumpforward.svg
├── loop
│ ├── loop-i18n.js
│ ├── loop.css
│ ├── loop.js
│ ├── loop.min.css
│ ├── loop.min.js
│ ├── loop.png
│ └── loop.svg
├── markers
│ ├── markers.js
│ └── markers.min.js
├── markersrolls
│ ├── markersrolls.js
│ └── markersrolls.min.js
├── picture-in-picture
│ ├── picture-in-picture-i18n.js
│ └── picture-in-picture.svg
├── playlist
│ ├── playlist-controls.svg
│ ├── playlist-i18n.js
│ ├── playlist.css
│ ├── playlist.js
│ ├── playlist.min.css
│ └── playlist.min.js
├── postroll
│ ├── postroll-i18n.js
│ ├── postroll.css
│ ├── postroll.js
│ ├── postroll.min.css
│ └── postroll.min.js
├── preview
│ ├── preview.js
│ └── preview.min.js
├── quality
│ ├── quality-i18n.js
│ ├── quality.css
│ ├── quality.js
│ ├── quality.min.css
│ └── quality.min.js
├── skip-back
│ ├── skip-back-i18n.js
│ ├── skip-back.js
│ ├── skip-back.min.js
│ └── skipback.svg
├── snapshot
│ ├── snapshot-i18n.js
│ └── snapshot.png
├── source-chooser
│ ├── settings.png
│ ├── settings.svg
│ ├── source-chooser-i18n.js
│ ├── source-chooser.css
│ ├── source-chooser.js
│ ├── source-chooser.min.css
│ └── source-chooser.min.js
├── speed
│ ├── speed-i18n.js
│ ├── speed.css
│ ├── speed.js
│ ├── speed.min.css
│ └── speed.min.js
├── stop
│ ├── stop-i18n.js
│ ├── stop.css
│ ├── stop.js
│ ├── stop.min.css
│ ├── stop.min.js
│ └── stop.svg
└── vrview
│ ├── cardboard.png
│ ├── cardboard.svg
│ ├── vrview.css
│ ├── vrview.js
│ ├── vrview.min.css
│ └── vrview.min.js
├── docs
├── a11y.md
├── ads-vast.md
├── ads.md
├── airplay.md
├── chromecast.md
├── context-menu.md
├── facebook-pixel.md
├── google-analytics.md
├── google-tag-manager.md
├── jump-forward.md
├── loop.md
├── markers.md
├── markersrolls.md
├── picture-in-picture.md
├── playlist.md
├── postroll.md
├── preview.md
├── quality.md
├── skip-back.md
├── snapshot.md
├── source-chooser.md
├── speed.md
├── stop.md
└── vrview.md
├── package-lock.json
├── package.json
└── src
├── .DS_Store
├── a11y
├── a11y-i18n.js
├── a11y.css
├── a11y.js
├── audio-description-icon.svg
└── video-description-icon.svg
├── ads-vast-vpaid
└── ads-vast-vpaid.js
├── ads
├── ads-i18n.js
├── ads.css
└── ads.js
├── airplay
├── airplay.css
├── airplay.js
├── airplay.png
└── airplay.svg
├── chromecast
├── chromecast.css
├── chromecast.js
├── chromecast.png
├── chromecast.svg
└── player.js
├── context-menu
├── context-menu-i18n.js
├── context-menu.css
└── context-menu.js
├── demo
└── mejs-controls.svg
├── facebook-pixel
└── facebook-pixel.js
├── google-analytics
└── google-analytics.js
├── google-tag-manager
└── google-tag-manager.js
├── header.js
├── jump-forward
├── jump-forward-i18n.js
├── jump-forward.js
└── jumpforward.svg
├── loop
├── loop-i18n.js
├── loop.css
├── loop.js
├── loop.png
└── loop.svg
├── markers
└── markers.js
├── markersrolls
└── markersrolls.js
├── picture-in-picture
├── picture-in-picture-i18n.js
├── picture-in-picture.css
├── picture-in-picture.js
└── picture-in-picture.svg
├── playlist
├── playlist-controls.svg
├── playlist-i18n.js
├── playlist.css
└── playlist.js
├── postroll
├── postroll-i18n.js
├── postroll.css
└── postroll.js
├── preview
└── preview.js
├── quality
├── quality-i18n.js
├── quality.css
└── quality.js
├── skip-back
├── skip-back-i18n.js
├── skip-back.js
└── skipback.svg
├── snapshot
├── Gruntfile.js
├── README.md
├── _config.yml
├── package-lock.json
├── package.json
├── snapshot-i18n.js
├── snapshot.css
├── snapshot.js
└── snapshot.png
├── source-chooser
├── settings.png
├── settings.svg
├── source-chooser-i18n.js
├── source-chooser.css
└── source-chooser.js
├── speed
├── speed-i18n.js
├── speed.css
└── speed.js
├── stop
├── stop-i18n.js
├── stop.css
├── stop.js
└── stop.svg
└── vrview
├── cardboard.png
├── cardboard.svg
├── vrview.css
└── vrview.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "comments": false,
3 | "presets": [
4 | ["env", {
5 | "targets": {
6 | "browsers": ["last 5 versions", "ie > 10", "ios > 7", "android > 3"]
7 | }
8 | }]
9 | ]
10 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "browser": true,
5 | "mocha": true,
6 | "node": true,
7 | "jquery": true
8 | },
9 | "extends": "eslint:recommended",
10 | "parserOptions": {
11 | "ecmaVersion": 6,
12 | "sourceType": "module"
13 | },
14 | "rules": {
15 | "no-console": 0,
16 | "no-undef" : 0,
17 | "no-case-declarations": 0
18 | }
19 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | *.jar binary
4 | *.mp3 binary
5 | *.mp4 binary
6 | *.ogv binary
7 | *.png binary
8 | *.webm binary
9 | *.swf binary
10 | *.swc binary
11 | *.fla binary
12 | *.xap binary
13 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | local-build
3 | # PhpStorm/WebStorm configuration
4 | .idea/*
5 | coverage
6 | npm-debug.log
7 | tmp
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "stylelint-order"
4 | ],
5 | "rules": {
6 | "color-hex-case": ["lower"],
7 | "color-hex-length": "short",
8 | "declaration-block-no-duplicate-properties": [
9 | true,
10 | {
11 | "ignore": [
12 | "consecutive-duplicates-with-different-values"
13 | ]
14 | }
15 | ],
16 | "function-comma-space-after": "always-single-line",
17 | "function-comma-space-before": "never",
18 | "indentation": 4,
19 | "length-zero-no-unit": true,
20 | "number-leading-zero": "always",
21 | "number-no-trailing-zeros": true,
22 | "order/order": [
23 | "custom-properties",
24 | "declarations"
25 | ],
26 | "order/properties-alphabetical-order": true,
27 | "property-case": "lower",
28 | "property-no-unknown": true,
29 | "selector-combinator-space-after": "always",
30 | "selector-combinator-space-before": "always",
31 | "selector-list-comma-newline-after": "always",
32 | "shorthand-property-no-redundant-values": true,
33 | "string-quotes": "single"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 |
2 | Instructions for the Maintainer
3 |
4 | **********************
5 | PREPARING A RELEASE - first steps, command line
6 | **********************
7 |
8 | - Create a dedicated branch for the release;
9 |
10 | git checkout master
11 | git checkout -b release_4.X.X
12 |
13 | - Run basic npm security checks;
14 |
15 | npm audit fix
16 |
17 | - update version
18 |
19 | package-lock.json: "version": "2.5.x",
20 | package.json: "version": "2.5.x",
21 |
22 | - check with shell command;
23 |
24 | head -4 package*.json | grep version
25 |
26 |
27 | - Update changelog.md
28 |
29 | - Build release;
30 |
31 | grunt
32 |
33 | - add/commit/push all including build/
34 |
35 | ```
36 | git add --all
37 | git commit -am "release 4.X.X"
38 | git push
39 | ```
40 |
41 | **********************
42 | PREPARING A RELEASE - second step on github.com
43 | **********************
44 |
45 | - prepare a new release using changelog.md
46 |
47 | **********************
48 | PREPARING A RELEASE - third step on npmjs.com
49 | **********************
50 |
--------------------------------------------------------------------------------
/demo/a11y.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MediaElement.js 4.2 - Accessibility Plugin
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
Accessibility Plugin
18 |
Back to Main
19 |
20 |
Video Player (w/o Voice-Over)
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/demo/airplay.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MediaElement.js 3.0 - AirPlay Plugin
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
AirPlay Plugin
19 |
Back to Main
20 |
21 |
This plugin displays a button to interact with an AirPlay device, if available.
22 |
23 |
It detects if media tag has the x-webkit-airplay attribute set as allow ; if not, the plugin sets it, to provide also native support.
24 |
25 |
NOTE: AirPlay only supports MP4, M(PEG)-DASH and HLS streaming natively.
26 |
27 |
Video Player
28 |
29 |
30 |
31 |
32 |
33 |
34 |
API
35 |
36 |
37 |
38 | Parameter
39 | Type
40 | Default
41 | Description
42 |
43 |
44 |
45 |
46 | airPlayTitle
47 | string
48 | null
49 | AirPlay button title for ARIA purposes
50 |
51 |
52 |
53 |
54 |
55 |
56 |
61 |
62 |
--------------------------------------------------------------------------------
/demo/demo.css:
--------------------------------------------------------------------------------
1 | #container {
2 | padding: 0 20px 50px;
3 | max-width: 800px;
4 | }
5 | .footnote {
6 | font-size: 0.7em;
7 | }
8 | table {
9 | border-collapse: collapse;
10 | max-width: 750px;
11 | }
12 | th, td {
13 | border-bottom: 1px solid #ddd;
14 | text-align: center;
15 | width: 120px;
16 | }
17 | th {
18 | background-color: #000;
19 | color: white;
20 | }
21 | a {
22 | overflow-wrap: break-word;
23 | word-wrap: break-word;
24 | -ms-word-break: break-all;
25 | word-break: break-all;
26 | word-break: break-word;
27 | -ms-hyphens: auto;
28 | -moz-hyphens: auto;
29 | -webkit-hyphens: auto;
30 | hyphens: auto;
31 | }
32 | td:last-child {
33 | width: 400px;
34 | text-align: left;
35 | }
36 | tr:nth-child(even) {
37 | background-color: #f2f2f2
38 | }
39 | pre {
40 | white-space: pre-wrap;
41 | tab-size: 2;
42 | background: black;
43 | color: white;
44 | max-width: 750px;
45 | }
46 | pre[data-lang]::before {
47 | content: attr(data-lang);
48 | display: block;
49 | background-color: #FFA500;
50 | background-image: -webkit-linear-gradient(top, #FFA500, #D67E21);
51 | background-image: linear-gradient(to bottom, #FFA500, #D67E21);
52 | padding: 10px;
53 | }
54 | code {
55 | font-family: "Courier New", Courier, monospace;
56 | padding: 10px 20px;
57 | display: inline-block;
58 | }
--------------------------------------------------------------------------------
/demo/end.html:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
You have reached the end of your media.
24 |
You can insert any HTML but just consider that this is not an iframe so
25 | whatever styles you intend to use must be restricted for this HTML piece only.
26 |
27 |
28 |
--------------------------------------------------------------------------------
/demo/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/demo/favicon.ico
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MediaElement.js 3.0 - Plugins
7 |
8 |
9 |
10 |
11 |
12 |
13 |
60 |
61 |
62 |
63 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/demo/mediaelement.vtt:
--------------------------------------------------------------------------------
1 | WEBVTT
2 |
3 | 0
4 | 00:00:00,1 --> 00:00:04
5 | HTML5 video and audio was supposed to be awesome, powerful, and fun.
6 |
7 | 1
8 | 00:00:04 --> 00:00:07
9 | But browser vendors couldn't agree on a codec
10 |
11 | 2
12 | 00:00:07 --> 00:00:10
13 | and older browsers don't support video at all.
14 |
15 | 3
16 | 00:00:10 --> 00:00:12
17 | This means video src="myfile.mp4" doesn't work ...
18 |
19 | 4
20 | 00:00:12 --> 00:00:14
21 | until now.
22 |
23 | 5
24 | 00:00:14 --> 00:00:18
25 | Introducing MediaElement.js, an HTML5 video and audio player
26 |
27 | 6
28 | 00:00:18 --> 00:00:21
29 | that looks and works the same in every browser (even iPhone and Android).
30 |
31 | 7
32 | 00:00:21 --> 00:00:24
33 | For older browsers, it has custom Flash plugins
34 |
35 | 8
36 | 00:00:24 --> 00:00:27
37 | that fully replicate the HTML5 MediaElement API
38 |
39 | 9
40 | 00:00:27 --> 00:00:30
41 | so you can build a consistent control UI using just HTML and CSS.
42 |
43 | 10
44 | 00:00:30 --> 00:00:33
45 | MediaElement.js even supports newer standards
46 |
47 | 11
48 | 00:00:33 --> 00:00:36
49 | like the <track> element that enables the subtitles you're reading right now.
50 |
51 | 12
52 | 00:00:36 --> 00:00:39
53 | Also, new media formats like M(PEG)-DASH and HLS can be played with MediaElement.
54 |
55 | 13
56 | 00:00:39 --> 00:00:42
57 | As a bonus, the Flash fallbacks allow you to use FLV and RTMP files.
58 |
59 | 14
60 | 00:00:42 --> 00:00:45
61 | Hope you like it.
--------------------------------------------------------------------------------
/demo/mejs-jump-forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 30
10 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/mejs-skip-back.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 30
10 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/postroll.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MediaElement.js 3.0 - Postroll Plugin
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
Postroll Plugin
19 |
Back to Main
20 |
21 |
This plugin allows the injection of any HTML content in an independent layer once the media has ended.
22 |
23 |
Video Player
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
The following snippet shows the proper HTML to activate the postroll functionality.
32 |
33 |
34 |
35 | <video width="640" height="360" preload="none" poster="/path/to/poster.jpg">
36 |
37 | <source src="/path/to/media.mp4" type="video/mp4">
38 | <link href="/path/to/postroll" rel="postroll">
39 |
40 | </video>
41 |
42 |
43 |
44 |
API
45 |
46 |
47 |
48 | Parameter
49 | Type
50 | Default
51 | Description
52 |
53 |
54 |
55 |
56 | postrollCloseText
57 | string
58 | null
59 | Title for button to Postroll layer for WARIA purposes
60 |
61 |
62 |
63 |
64 |
65 |
66 |
71 |
72 |
--------------------------------------------------------------------------------
/demo/speed.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MediaElement.js 3.0 - Speed Plugin
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Speed Plugin
20 |
Back to Main
21 |
22 |
This plugin allows the generation of a menu with different video/audio speed.
23 |
24 |
Video Player
25 |
26 |
27 |
Video Player 1
28 |
29 |
30 |
31 | Video Player 2
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/dist/a11y/a11y-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.de !== undefined) {
4 | mejs.i18n.de['mejs.a11y-audio-description'] = 'Audio Deskription An/Aus';
5 | mejs.i18n.de['mejs.a11y-video-description'] = 'Video Deskription An/Aus';
6 | }
7 |
8 | if (mejs.i18n.fr !== undefined) {
9 | mejs.i18n.fr['mejs.a11y-audio-description'] = 'Audio-description étendue On/Off';
10 | mejs.i18n.fr['mejs.a11y-video-description'] = 'Langue des signes On/Off';
11 | }
12 |
13 | if (mejs.i18n.nl !== undefined) {
14 | mejs.i18n.nl['mejs.a11y-audio-description'] = 'Audiobeschrijving Aan/Uit';
15 | mejs.i18n.nl['mejs.a11y-video-description'] = 'Gebarentaal Aan/Uit';
16 | }
17 |
18 | if (mejs.i18n.tr !== undefined) {
19 | mejs.i18n.tr['mejs.a11y-audio-description'] = 'Sesli betimleme değiştir';
20 | mejs.i18n.tr['mejs.a11y-video-description'] = 'Görüntülü betimleme değişti';
21 | }
22 |
--------------------------------------------------------------------------------
/dist/a11y/a11y.css:
--------------------------------------------------------------------------------
1 | .mejs-volume-button.hidden,
2 | .mejs__volume-button.hidden {
3 | display: none;
4 | }
5 |
6 | .mejs-audio-description-player,
7 | .mejs__audio-description-player {
8 | display: none;
9 | }
10 |
--------------------------------------------------------------------------------
/dist/a11y/a11y.min.css:
--------------------------------------------------------------------------------
1 | .mejs-audio-description-player,.mejs-volume-button.hidden,.mejs__audio-description-player,.mejs__volume-button.hidden{display:none}
--------------------------------------------------------------------------------
/dist/a11y/audio-description-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/a11y/video-description-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/ads/ads.css:
--------------------------------------------------------------------------------
1 | .mejs__ads > a,
2 | .mejs-ads > a {
3 | display: block;
4 | height: 100%;
5 | position: absolute;
6 | right: 0;
7 | top: 0;
8 | width: 100%;
9 | }
10 | .mejs__ads-skip-block,
11 | .mejs-ads-skip-block {
12 | background: #000;
13 | background: rgba(0, 0, 0, 0.5);
14 | color: #fff;
15 | display: block;
16 | padding: 10px;
17 | position: absolute;
18 | right: 0;
19 | top: 0;
20 | }
21 | .mejs__ads-skip-button,
22 | .mejs-ads-skip-button {
23 | cursor: pointer;
24 | }
25 | .mejs__ads-skip-button:hover,
26 | .mejs-ads-skip-button:hover {
27 | text-decoration: underline;
28 | }
29 |
--------------------------------------------------------------------------------
/dist/ads/ads.min.css:
--------------------------------------------------------------------------------
1 | .mejs-ads>a,.mejs__ads>a{display:block;height:100%;position:absolute;right:0;top:0;width:100%}.mejs-ads-skip-block,.mejs__ads-skip-block{background:#000;background:rgba(0,0,0,.5);color:#fff;display:block;padding:10px;position:absolute;right:0;top:0}.mejs-ads-skip-button,.mejs__ads-skip-button{cursor:pointer}.mejs-ads-skip-button:hover,.mejs__ads-skip-button:hover{text-decoration:underline}
--------------------------------------------------------------------------------
/dist/airplay/airplay.css:
--------------------------------------------------------------------------------
1 | .mejs__airplay-button > button,
2 | .mejs-airplay-button > button {
3 | background: url('airplay.svg') no-repeat 0 4px;
4 | }
5 |
6 | .mejs__airplay-button > button .fill,
7 | .mejs-airplay-button > button .fill {
8 | fill: #fff;
9 | }
10 |
11 | .mejs__airplay-button > button.active .fill,
12 | .mejs-airplay-button > button.active .fill {
13 | fill: #66a8cc;
14 | }
15 |
--------------------------------------------------------------------------------
/dist/airplay/airplay.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i';
30 |
31 | button.addEventListener('click', function () {
32 | t.media.originalNode.webkitShowPlaybackTargetPicker();
33 | });
34 |
35 | var acceptAirPlay = t.media.originalNode.getAttribute('x-webkit-airplay');
36 | if (!acceptAirPlay || acceptAirPlay !== 'allow') {
37 | t.media.originalNode.setAttribute('x-webkit-airplay', 'allow');
38 | }
39 |
40 | t.media.originalNode.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', function () {
41 | var name = t.media.originalNode.webkitCurrentPlaybackTargetIsWireless ? 'Started' : 'Stopped',
42 | status = t.media.originalNode.webkitCurrentPlaybackTargetIsWireless ? 'active' : '',
43 | icon = button.querySelector('button'),
44 | event = mejs.Utils.createEvent('airplay' + name, t.media);
45 | t.media.dispatchEvent(event);
46 |
47 | if (status === 'active') {
48 | mejs.Utils.addClass(icon, 'active');
49 | } else {
50 | mejs.Utils.removeClass(icon, 'active');
51 | }
52 | });
53 |
54 | t.media.originalNode.addEventListener('webkitplaybacktargetavailabilitychanged', function (e) {
55 | if (e.availability === 'available') {
56 | t.addControlElement(button, 'airplay');
57 | }
58 | });
59 | }
60 | });
61 |
62 | },{}]},{},[1]);
63 |
--------------------------------------------------------------------------------
/dist/airplay/airplay.min.css:
--------------------------------------------------------------------------------
1 | .mejs-airplay-button>button,.mejs__airplay-button>button{background:url(airplay.svg) no-repeat 0 4px}.mejs-airplay-button>button .fill,.mejs__airplay-button>button .fill{fill:#fff}.mejs-airplay-button>button.active .fill,.mejs__airplay-button>button.active .fill{fill:#66a8cc}
--------------------------------------------------------------------------------
/dist/airplay/airplay.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
12 | !function n(l,o,s){function d(t,e){if(!o[t]){if(!l[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(c)return c(t,!0);var a=new Error("Cannot find module '"+t+"'");throw a.code="MODULE_NOT_FOUND",a}var r=o[t]={exports:{}};l[t][0].call(r.exports,function(e){return d(l[t][1][e]||e)},r,r.exports,n,l,o,s)}return o[t].exports}for(var c="function"==typeof require&&require,e=0;e',n.addEventListener("click",function(){r.media.originalNode.webkitShowPlaybackTargetPicker()});var t=r.media.originalNode.getAttribute("x-webkit-airplay");t&&"allow"===t||r.media.originalNode.setAttribute("x-webkit-airplay","allow"),r.media.originalNode.addEventListener("webkitcurrentplaybacktargetiswirelesschanged",function(){var e=r.media.originalNode.webkitCurrentPlaybackTargetIsWireless?"Started":"Stopped",t=r.media.originalNode.webkitCurrentPlaybackTargetIsWireless?"active":"",i=n.querySelector("button"),a=mejs.Utils.createEvent("airplay"+e,r.media);r.media.dispatchEvent(a),"active"===t?mejs.Utils.addClass(i,"active"):mejs.Utils.removeClass(i,"active")}),r.media.originalNode.addEventListener("webkitplaybacktargetavailabilitychanged",function(e){"available"===e.availability&&r.addControlElement(n,"airplay")})}}})},{}]},{},[1]);
--------------------------------------------------------------------------------
/dist/airplay/airplay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/airplay/airplay.png
--------------------------------------------------------------------------------
/dist/airplay/airplay.svg:
--------------------------------------------------------------------------------
1 | 7
--------------------------------------------------------------------------------
/dist/chromecast/chromecast.css:
--------------------------------------------------------------------------------
1 | .mejs__chromecast-button > button,
2 | .mejs-chromecast-button > button {
3 | --disconnected-color: #fff;
4 | background: none;
5 | display: inline-block;
6 | }
7 | .mejs__chromecast-container,
8 | .mejs-chromecast-container {
9 | background: #000;
10 | color: #fff;
11 | font-size: 10px;
12 | left: 0;
13 | padding: 5px;
14 | position: absolute;
15 | top: 0;
16 | z-index: 1;
17 | }
18 |
19 | .mejs__chromecast-layer > img,
20 | .mejs-chromecast-layer > img {
21 | left: 0;
22 | position: absolute;
23 | top: 0;
24 | z-index: 0;
25 | }
26 |
27 | .mejs__chromecast-icon,
28 | .mejs-chromecast-icon {
29 | background: url('chromecast.svg') no-repeat 0 0;
30 | display: inline-block;
31 | height: 14px;
32 | margin-right: 5px;
33 | width: 17px;
34 | }
--------------------------------------------------------------------------------
/dist/chromecast/chromecast.min.css:
--------------------------------------------------------------------------------
1 | .mejs-chromecast-button>button,.mejs__chromecast-button>button{--disconnected-color:#fff;background:none;display:inline-block}.mejs-chromecast-container,.mejs__chromecast-container{background:#000;color:#fff;font-size:10px;left:0;padding:5px;position:absolute;top:0;z-index:1}.mejs-chromecast-layer>img,.mejs__chromecast-layer>img{left:0;position:absolute;top:0;z-index:0}.mejs-chromecast-icon,.mejs__chromecast-icon{background:url(chromecast.svg) no-repeat 0 0;display:inline-block;height:14px;margin-right:5px;width:17px}
--------------------------------------------------------------------------------
/dist/chromecast/chromecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/chromecast/chromecast.png
--------------------------------------------------------------------------------
/dist/chromecast/chromecast.svg:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/dist/context-menu/context-menu.css:
--------------------------------------------------------------------------------
1 | .mejs__contextmenu,
2 | .mejs-contextmenu {
3 | background: #fff;
4 | border: solid 1px #999;
5 | border-radius: 4px;
6 | left: 0;
7 | padding: 10px;
8 | position: absolute;
9 | top: 0;
10 | width: 150px;
11 | z-index: 9999999999; /* make sure it shows on fullscreen */
12 | }
13 |
14 | .mejs__contextmenu-separator,
15 | .mejs-contextmenu-separator {
16 | background: #333;
17 | font-size: 0;
18 | height: 1px;
19 | margin: 5px 6px;
20 | }
21 |
22 | .mejs__contextmenu-item,
23 | .mejs-contextmenu-item {
24 | color: #333;
25 | cursor: pointer;
26 | font-size: 12px;
27 | padding: 4px 6px;
28 | }
29 |
30 | .mejs__contextmenu-item:hover,
31 | .mejs-contextmenu-item:hover {
32 | background: #2c7c91;
33 | color: #fff;
34 | }
35 |
--------------------------------------------------------------------------------
/dist/context-menu/context-menu.min.css:
--------------------------------------------------------------------------------
1 | .mejs-contextmenu,.mejs__contextmenu{background:#fff;border:1px solid #999;border-radius:4px;left:0;padding:10px;position:absolute;top:0;width:150px;z-index:1}.mejs-contextmenu-separator,.mejs__contextmenu-separator{background:#333;font-size:0;height:1px;margin:5px 6px}.mejs-contextmenu-item,.mejs__contextmenu-item{color:#333;cursor:pointer;font-size:12px;padding:4px 6px}.mejs-contextmenu-item:hover,.mejs__contextmenu-item:hover{background:#2c7c91;color:#fff}
--------------------------------------------------------------------------------
/dist/facebook-pixel/facebook-pixel.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i
2 |
3 |
4 |
5 |
6 |
7 |
8 | 30
9 |
10 |
11 |
--------------------------------------------------------------------------------
/dist/loop/loop-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.loop'] = 'Commuta Bucle';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.loop'] = 'Přepnout smyčku';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.loop'] = 'Wiederholung (de-)aktivieren';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.loop'] = 'Alternar Repetición';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.loop'] = 'حلقه تعویض';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.loop'] = 'Répéter';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.loop'] = 'Uključi/isključi ponavljanje';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.loop'] = 'Húzza át a kapcsolót';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.loop'] = 'Passare il ciclo';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.loop'] = 'トグルループ';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.loop'] = '루프 토글';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.loop'] = 'Togol ulangan';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.loop'] = 'Schakellus';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.loop'] = 'Zapętl';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.loop'] = 'Loop alternativo';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.loop'] = 'Comutați buclă';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.loop'] = 'Зациклить воспроизведение';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.loop'] = 'Prepínať slučku';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.loop'] = 'Repetera';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.loop'] = 'Döngü';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.loop'] = 'Повторювати';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.loop'] = '切換循環';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.loop'] = '切换循环';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/loop/loop.css:
--------------------------------------------------------------------------------
1 | .mejs__loop-button > button,
2 | .mejs-loop-button > button {
3 | background: url('loop.svg') no-repeat transparent;
4 | }
5 | .mejs__loop-off > button,
6 | .mejs-loop-off > button {
7 | background-position: -20px 1px;
8 | }
9 |
10 | .mejs__loop-on > button,
11 | .mejs-loop-on > button {
12 | background-position: 0 1px;
13 | }
14 |
--------------------------------------------------------------------------------
/dist/loop/loop.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i';
28 |
29 | t.addControlElement(loop, 'loop');
30 |
31 | loop.addEventListener('click', function () {
32 | player.options.loop = !player.options.loop;
33 | if (player.options.loop) {
34 | mejs.Utils.removeClass(loop, t.options.classPrefix + 'loop-off');
35 | mejs.Utils.addClass(loop, t.options.classPrefix + 'loop-on');
36 | } else {
37 | mejs.Utils.removeClass(loop, t.options.classPrefix + 'loop-on');
38 | mejs.Utils.addClass(loop, t.options.classPrefix + 'loop-off');
39 | }
40 | });
41 | }
42 | });
43 |
44 | },{}]},{},[1]);
45 |
--------------------------------------------------------------------------------
/dist/loop/loop.min.css:
--------------------------------------------------------------------------------
1 | .mejs-loop-button>button,.mejs__loop-button>button{background:url(loop.svg) no-repeat transparent}.mejs-loop-off>button,.mejs__loop-off>button{background-position:-20px 1px}.mejs-loop-on>button,.mejs__loop-on>button{background-position:0 1px}
--------------------------------------------------------------------------------
/dist/loop/loop.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
12 | !function i(l,r,p){function a(t,o){if(!r[t]){if(!l[t]){var e="function"==typeof require&&require;if(!o&&e)return e(t,!0);if(f)return f(t,!0);var s=new Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}var n=r[t]={exports:{}};l[t][0].call(n.exports,function(o){return a(l[t][1][o]||o)},n,n.exports,i,l,r,p)}return r[t].exports}for(var f="function"==typeof require&&require,o=0;o',t.addControlElement(s,"loop"),s.addEventListener("click",function(){o.options.loop=!o.options.loop,o.options.loop?(mejs.Utils.removeClass(s,t.options.classPrefix+"loop-off"),mejs.Utils.addClass(s,t.options.classPrefix+"loop-on")):(mejs.Utils.removeClass(s,t.options.classPrefix+"loop-on"),mejs.Utils.addClass(s,t.options.classPrefix+"loop-off"))})}})},{}]},{},[1]);
--------------------------------------------------------------------------------
/dist/loop/loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/loop/loop.png
--------------------------------------------------------------------------------
/dist/loop/loop.svg:
--------------------------------------------------------------------------------
1 | 4
--------------------------------------------------------------------------------
/dist/markers/markers.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
12 | !function i(a,s,l){function f(e,r){if(!s[e]){if(!a[e]){var t="function"==typeof require&&require;if(!r&&t)return t(e,!0);if(m)return m(e,!0);var o=new Error("Cannot find module '"+e+"'");throw o.code="MODULE_NOT_FOUND",o}var n=s[e]={exports:{}};a[e][0].call(n.exports,function(r){return f(a[e][1][r]||r)},n,n.exports,i,a,s,l)}return s[e].exports}for(var m="function"==typeof require&&require,r=0;r=this.media.duration||t<0)){var o=100*t/this.media.duration,i=r[s];i.style.width=this.options.markersRollsWidth+"px",i.style.left=o+"%",i.style.background=this.options.markersRollsColor,s++}}})},{}]},{},[1]);
--------------------------------------------------------------------------------
/dist/picture-in-picture/picture-in-picture-i18n.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | if(mejs.i18n.es !== undefined) {
4 | mejs.i18n.es['mejs.picture-in-pictureText'] = 'Picture in picture';
5 | }
6 | if (mejs.i18n.de !== undefined) {
7 | mejs.i18n.de['mejs.picture-in-pictureText'] = 'Bild in Bild';
8 | }
9 | if(mejs.i18n.fr !== undefined) {
10 | mejs.i18n.fr['mejs.picture-in-pictureText'] = 'Image dans l’image';
11 | }
12 | if(mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.picture-in-pictureText'] = 'Imagen dentro de imagen';
14 | }
15 |
16 |
17 | // TODO Add more languages for the title attribute
18 |
--------------------------------------------------------------------------------
/dist/picture-in-picture/picture-in-picture.svg:
--------------------------------------------------------------------------------
1 |
2 |
13 |
15 |
19 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/dist/postroll/postroll-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.close'] = 'Tancar';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.close'] = 'Zavřít';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.close'] = 'Schließen';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.close'] = 'Cerrar';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.close'] = 'نزدیک';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.close'] = 'Fermer';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.close'] = 'Zatvori';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.close'] = 'Bezárás';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.close'] = 'Chiudere';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.close'] = '閉じる';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.close'] = '종료';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.close'] = 'Tutup';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.close'] = 'Sluiten';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.close'] = 'Zamknij';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.close'] = 'Fechar';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.close'] = 'Închide';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.close'] = 'Закрыть';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.close'] = 'Zavrieť';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.close'] = 'Stäng';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.close'] = 'Kapat';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.close'] = 'Закрити';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.close'] = '關閉';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.close'] = '关闭';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/postroll/postroll.css:
--------------------------------------------------------------------------------
1 | .mejs__postroll-layer,
2 | .mejs-postroll-layer {
3 | background: rgba(50, 50, 50, 0.7);
4 | bottom: 0;
5 | height: 100%;
6 | left: 0;
7 | overflow: hidden;
8 | position: absolute;
9 | width: 100%;
10 | z-index: 1000;
11 | }
12 |
13 | .mejs__postroll-layer-content,
14 | .mejs-postroll-layer-content {
15 | height: 100%;
16 | width: 100%;
17 | }
18 | .mejs__postroll-close,
19 | .mejs-postroll-close {
20 | background: rgba(50, 50, 50, 0.7);
21 | color: #fff;
22 | cursor: pointer;
23 | padding: 4px;
24 | position: absolute;
25 | right: 0;
26 | top: 0;
27 | z-index: 100;
28 | }
29 |
--------------------------------------------------------------------------------
/dist/postroll/postroll.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i' + postrollTitle + '' + ('
');
30 | player.postroll.style.display = 'none';
31 |
32 | layers.insertBefore(player.postroll, layers.firstChild);
33 |
34 | player.postroll.querySelector('.' + t.options.classPrefix + 'postroll-close').addEventListener('click', function (e) {
35 | this.parentNode.style.display = 'none';
36 | e.preventDefault();
37 | e.stopPropagation();
38 | });
39 |
40 | t.media.addEventListener('ended', function () {
41 | mejs.Utils.ajax(postrollLink.getAttribute('href'), 'html', function (data) {
42 | layers.querySelector('.' + t.options.classPrefix + 'postroll-layer-content').innerHTML = data;
43 | });
44 | player.postroll.style.display = 'block';
45 | }, false);
46 |
47 | t.media.addEventListener('seeked', function () {
48 | player.postroll.style.display = 'none';
49 | }, false);
50 |
51 | t.media.addEventListener('playing', function () {
52 | player.postroll.style.display = 'none';
53 | }, false);
54 | }
55 | }
56 | });
57 |
58 | },{}]},{},[1]);
59 |
--------------------------------------------------------------------------------
/dist/postroll/postroll.min.css:
--------------------------------------------------------------------------------
1 | .mejs-postroll-layer,.mejs__postroll-layer{background:rgba(50,50,50,.7);bottom:0;height:100%;left:0;overflow:hidden;position:absolute;width:100%;z-index:2}.mejs-postroll-layer-content,.mejs__postroll-layer-content{height:100%;width:100%}.mejs-postroll-close,.mejs__postroll-close{background:rgba(50,50,50,.7);color:#fff;cursor:pointer;padding:4px;position:absolute;right:0;top:0;z-index:1}
--------------------------------------------------------------------------------
/dist/postroll/postroll.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
12 | !function r(n,i,a){function p(t,e){if(!i[t]){if(!n[t]){var o="function"==typeof require&&require;if(!e&&o)return o(t,!0);if(c)return c(t,!0);var s=new Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}var l=i[t]={exports:{}};n[t][0].call(l.exports,function(e){return p(n[t][1][e]||e)},l,l.exports,r,n,i,a)}return i[t].exports}for(var c="function"==typeof require&&require,e=0;e'+l+'
',e.postroll.style.display="none",o.insertBefore(e.postroll,o.firstChild),e.postroll.querySelector("."+s.options.classPrefix+"postroll-close").addEventListener("click",function(e){this.parentNode.style.display="none",e.preventDefault(),e.stopPropagation()}),s.media.addEventListener("ended",function(){mejs.Utils.ajax(r.getAttribute("href"),"html",function(e){o.querySelector("."+s.options.classPrefix+"postroll-layer-content").innerHTML=e}),e.postroll.style.display="block"},!1),s.media.addEventListener("seeked",function(){e.postroll.style.display="none"},!1),s.media.addEventListener("playing",function(){e.postroll.style.display="none"},!1))}})},{}]},{},[1]);
--------------------------------------------------------------------------------
/dist/quality/quality-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.quality-chooser']= 'Selector de qualitat';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.quality-chooser']= 'Kvalitní výběr';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.quality-chooser']= 'Qualitätswähler';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.quality-chooser']= 'Selector de calidad';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.quality-chooser']= 'انتخاب کننده کیفیت';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.quality-chooser']= 'Sélecteur de qualité';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.quality-chooser']= 'Kvalitetni birač';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.quality-chooser']= 'Minőségi választó';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.quality-chooser']= 'Qualità scelto';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.quality-chooser']= '品質チューザー';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.quality-chooser']= '품질 선택자';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.quality-chooser']= 'Pilih kualiti';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.quality-chooser']= 'Kwaliteit kiezer';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.quality-chooser']= 'Chooser jakości';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.quality-chooser']= 'Escolha de qualidade';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.quality-chooser']= 'Alegere de calitate';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.quality-chooser']= 'Выбор качества';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.quality-chooser']= 'Kvalitný výber';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.quality-chooser']= 'Kvalitetsvalare';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.quality-chooser']= 'Kalite';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.quality-chooser']= 'Вибір якості';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.quality-chooser']= '質量選擇';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.quality-chooser']= '质量选择';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/quality/quality.css:
--------------------------------------------------------------------------------
1 | .mejs__qualities-selector.mejs__offscreen {
2 | display: none;
3 | }
4 |
5 | .mejs__qualities-button,
6 | .mejs-qualities-button {
7 | position: relative;
8 | width: auto;
9 | }
10 |
11 | .mejs__qualities-button > button,
12 | .mejs-qualities-button > button {
13 | background: transparent;
14 | color: #fff;
15 | font-size: 0.6875rem;
16 | font-weight: 700;
17 | position: static;
18 | width: auto;
19 | }
20 |
21 | .mejs__qualities-selector,
22 | .mejs-qualities-selector {
23 | background: rgba(50, 50, 50, 0.7);
24 | border: 0.063rem solid transparent;
25 | border-radius: 0;
26 | height: 6.25rem;
27 | left: -0.625rem;
28 | overflow: hidden;
29 | padding: 0;
30 | position: absolute;
31 | top: -6.25rem;
32 | width: 3.75rem;
33 | }
34 |
35 | .mejs__qualities-selector ul,
36 | .mejs-qualities-selector ul {
37 | display: block;
38 | list-style-type: none !important;
39 | margin: 0;
40 | overflow: hidden;
41 | padding: 0;
42 | }
43 |
44 | .mejs__qualities-selector li,
45 | .mejs-qualities-selector li {
46 | border: 0.06rem solid transparent;
47 | color: #fff;
48 | cursor: pointer;
49 | display: block;
50 | list-style-type: none!important;
51 | overflow: hidden;
52 | padding: 0 0.625rem;
53 | }
54 |
55 | .mejs__qualities-selector li:hover,
56 | .mejs-qualities-selector li:hover {
57 | background-color: rgba(255, 255, 255, 0.2);
58 | cursor: pointer;
59 | }
60 |
61 | .mejs__qualities-selector li:focus-within,
62 | .mejs-qualities-selector li:focus-within {
63 | border-color: #fff;
64 | }
65 |
66 | .mejs__qualities-selector input,
67 | .mejs-qualities-selector input {
68 | clear: both;
69 | float: left;
70 | left: -62.5rem;
71 | margin: 0.188rem 0.188rem 0 0.313rem;
72 | position: absolute;
73 | }
74 |
75 | .mejs__qualities-selector label,
76 | .mejs-qualities-selector label {
77 | cursor: pointer;
78 | float: left;
79 | font-size: 0.625rem;
80 | padding: 0.375rem 0;
81 | width: 3.438rem;
82 | }
83 |
84 | .mejs__qualities-selected,
85 | .mejs-qualities-selected {
86 | color: rgba(33, 248, 248, 1);
87 | }
88 |
--------------------------------------------------------------------------------
/dist/quality/quality.min.css:
--------------------------------------------------------------------------------
1 | .mejs__qualities-selector.mejs__offscreen{display:none}.mejs-qualities-button,.mejs__qualities-button{position:relative;width:auto}.mejs-qualities-button>button,.mejs__qualities-button>button{background:transparent;color:#fff;font-size:.6875rem;font-weight:700;position:static;width:auto}.mejs-qualities-selector,.mejs__qualities-selector{background:rgba(50,50,50,.7);border:.063rem solid transparent;border-radius:0;height:6.25rem;left:-.625rem;overflow:hidden;padding:0;position:absolute;top:-6.25rem;width:3.75rem}.mejs-qualities-selector ul,.mejs__qualities-selector ul{display:block;list-style-type:none!important;margin:0;overflow:hidden;padding:0}.mejs-qualities-selector li,.mejs__qualities-selector li{border:.06rem solid transparent;color:#fff;cursor:pointer;display:block;list-style-type:none!important;overflow:hidden;padding:0 .625rem}.mejs-qualities-selector li:hover,.mejs__qualities-selector li:hover{background-color:hsla(0,0%,100%,.2);cursor:pointer}.mejs-qualities-selector li:focus-within,.mejs__qualities-selector li:focus-within{border-color:#fff}.mejs-qualities-selector input,.mejs__qualities-selector input{clear:both;float:left;left:-62.5rem;margin:.188rem .188rem 0 .313rem;position:absolute}.mejs-qualities-selector label,.mejs__qualities-selector label{cursor:pointer;float:left;font-size:.625rem;padding:.375rem 0;width:3.438rem}.mejs-qualities-selected,.mejs__qualities-selected{color:#21f8f8}
--------------------------------------------------------------------------------
/dist/skip-back/skip-back.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i
2 |
3 |
4 |
5 |
6 |
7 | 30
8 |
9 |
--------------------------------------------------------------------------------
/dist/snapshot/snapshot-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.snapshot'] = ['Retornar 1 segon', 'Retornar %1 segons'];
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.snapshot'] = ['Přeskočte zpět o 1 sekundu', 'Přeskočte zpět %1 vteřiny', 'Přeskočte zpět %1 sekund'];
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.snapshot'] = ['1 Sekunde zurückspulen', '%1 Sekunden zurückspulen'];
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.snapshot'] = ['Rebobinar 1 segundo', 'Rebobinar %1 segundos'];
14 | }
15 | if (mejs.i18n.fr !== undefined) {
16 | mejs.i18n.fr['mejs.snapshot'] = ['Reculer de %1 seconde', 'Reculer de %1 secondes'];
17 | }
18 | if (mejs.i18n.fa !== undefined) {
19 | mejs.i18n.fa['mejs.snapshot'] = '%1 ثانیه به عقب برگردید';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.snapshot'] = ['Skoči natrag 1 sekundu', 'Skoči natrag %1 sekunde', 'Skoči natrag %1 sekundi'];
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.snapshot'] = ['Menj vissza 1 másodpercig', 'Ugrás vissza %1 másodperccel'];
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.snapshot'] = ['Riavvolgere 1 secondo', 'Riavvolgere %1 secondi'];
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.snapshot'] = '%1秒スキップバックする';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.snapshot'] = '%1초 를 뒤로 건너뛰세요';
35 | }
36 | if (mejs.i18n.nl !== undefined) {
37 | mejs.i18n.nl['mejs.snapshot'] = ['Sla 1 seconde terug', 'Sla %1 seconden terug'];
38 | }
39 | if (mejs.i18n.pl !== undefined) {
40 | mejs.i18n.pl['mejs.snapshot'] = ['Cofnij o 1 sekundę', 'Cofnij o %1 sekundy', 'Cofnij o %1 sekund'];
41 | }
42 | if (mejs.i18n.pt !== undefined) {
43 | mejs.i18n.pt['mejs.snapshot'] = ['Retroceder %1 segundo', 'Retroceder %1 segundos'];
44 | }
45 | if (mejs.i18n.ro !== undefined) {
46 | mejs.i18n.ro['mejs.snapshot'] = ['Treceți înapoi 1 secundă', 'Treceți înapoi în %1 secunde'];
47 | }
48 | if (mejs.i18n.ru !== undefined) {
49 | mejs.i18n.ru['mejs.snapshot'] = ['Перейти назад на %1 секунду', 'Перейти назад на %1 секунды', 'Перейти назад на %1 секунд'];
50 | }
51 | if (mejs.i18n.sk !== undefined) {
52 | mejs.i18n.sk['mejs.snapshot'] = ['Preskočte späť 1 sekundu', 'Preskočte %1 sekundy', 'Preskočte späť %1 sekúnd'];
53 | }
54 | if (mejs.i18n.sv !== undefined) {
55 | mejs.i18n.sv['mejs.snapshot'] = ['Hoppa tillbaka 1 sekund', 'Hoppa tillbaka %1 sekunder'];
56 | }
57 | if (mejs.i18n.tr !== undefined) {
58 | mejs.i18n.tr['mejs.snapshot'] = ['1 saniye geri atla', '%1 saniye geri atla'];
59 | }
60 | if (mejs.i18n.uk !== undefined) {
61 | mejs.i18n.uk['mejs.snapshot'] = ['Перейти назад на %1 секунду', 'Перейти назад на %1 секунди', 'Перейти назад на %1 секунд'];
62 | }
63 | if (mejs.i18n.zh !== undefined) {
64 | mejs.i18n.zh['mejs.snapshot'] = '跳躍式迴繞%1秒';
65 | }
66 | if (mejs.i18n['zh-CN'] !== undefined) {
67 | mejs.i18n['zh-CN']['mejs.snapshot'] = '后退%1秒';
68 | }
69 |
--------------------------------------------------------------------------------
/dist/snapshot/snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/snapshot/snapshot.png
--------------------------------------------------------------------------------
/dist/source-chooser/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/source-chooser/settings.png
--------------------------------------------------------------------------------
/dist/source-chooser/settings.svg:
--------------------------------------------------------------------------------
1 | 3
--------------------------------------------------------------------------------
/dist/source-chooser/source-chooser-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.source-chooser']= 'Selector de font';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.source-chooser']= 'Zdrojový výběr';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.source-chooser']= 'Quellenauswahl';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.source-chooser']= 'Selector de media';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.source-chooser']= 'انتخاب کننده منبع';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.source-chooser']= 'Sélecteur de média';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.source-chooser']= 'Obabir izvora';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.source-chooser']= 'Forrásválasztó';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.source-chooser']= 'Selezionatore di origine';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.source-chooser']= 'ソースセレクタ';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.source-chooser']= '소스 선택기';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.source-chooser']= 'Pilih sumber';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.source-chooser']= 'Bronkeuze';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.source-chooser']= 'Wybór źródła';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.source-chooser']= 'Escolhedor de fontes';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.source-chooser']= 'Sursă de selecție';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.source-chooser']= 'Переключатель источника';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.source-chooser']= 'Zdroj výberu';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.source-chooser']= 'Välj källa';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.source-chooser']= 'Kaynak Seçici';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.source-chooser']= 'Вибір джерела';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.source-chooser']= '源選擇器';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.source-chooser']= '源选择器';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/source-chooser/source-chooser.css:
--------------------------------------------------------------------------------
1 | .mejs__sourcechooser-button,
2 | .mejs-sourcechooser-button {
3 | position: relative;
4 | }
5 |
6 | .mejs__sourcechooser-button > button,
7 | .mejs-sourcechooser-button > button {
8 | background: url('settings.svg') transparent no-repeat;
9 | background-position: 0 1px;
10 | }
11 |
12 | .mejs__sourcechooser-button .mejs__sourcechooser-selector,
13 | .mejs-sourcechooser-button .mejs-sourcechooser-selector {
14 | background: rgba(50, 50, 50, 0.7);
15 | border: solid 1px transparent;
16 | border-radius: 0;
17 | bottom: 40px;
18 | height: 100px;
19 | overflow: hidden;
20 | padding: 0;
21 | position: absolute;
22 | right: -10px;
23 | width: 130px;
24 | }
25 |
26 | .mejs__sourcechooser-selector ul,
27 | .mejs-sourcechooser-selector ul {
28 | display: block;
29 | list-style-type: none !important;
30 | margin: 0;
31 | overflow: hidden;
32 | padding: 0;
33 | }
34 |
35 | .mejs__sourcechooser-selector li,
36 | .mejs-sourcechooser-selector li {
37 | color: #fff;
38 | display: block;
39 | list-style-type: none !important;
40 | margin: 0;
41 | overflow: hidden;
42 | padding: 5px 0;
43 | }
44 | .mejs__sourcechooser-selector li:hover,
45 | .mejs-sourcechooser-selector li:hover {
46 | background-color: rgba(255, 255, 255, 0.2);
47 | cursor: pointer;
48 | }
49 |
50 | .mejs__sourcechooser-selector input,
51 | .mejs-sourcechooser-selector input {
52 | clear: both;
53 | float: left;
54 | margin: 3px 3px 0 0;
55 | }
56 |
57 | .mejs__sourcechooser-selector label,
58 | .mejs-sourcechooser-selector label {
59 | display: inline-block;
60 | float: left;
61 | font-size: 12px;
62 | line-height: 15px;
63 | padding: 4px 0 0;
64 | width: 100px;
65 | }
66 |
--------------------------------------------------------------------------------
/dist/source-chooser/source-chooser.min.css:
--------------------------------------------------------------------------------
1 | .mejs-sourcechooser-button,.mejs__sourcechooser-button{position:relative}.mejs-sourcechooser-button>button,.mejs__sourcechooser-button>button{background:url(settings.svg) transparent no-repeat;background-position:0 1px}.mejs-sourcechooser-button .mejs-sourcechooser-selector,.mejs__sourcechooser-button .mejs__sourcechooser-selector{background:rgba(50,50,50,.7);border:1px solid transparent;border-radius:0;bottom:40px;height:100px;overflow:hidden;padding:0;position:absolute;right:-10px;width:130px}.mejs-sourcechooser-selector ul,.mejs__sourcechooser-selector ul{display:block;list-style-type:none!important;margin:0;overflow:hidden;padding:0}.mejs-sourcechooser-selector li,.mejs__sourcechooser-selector li{color:#fff;display:block;list-style-type:none!important;margin:0;overflow:hidden;padding:5px 0}.mejs-sourcechooser-selector li:hover,.mejs__sourcechooser-selector li:hover{background-color:hsla(0,0%,100%,.2);cursor:pointer}.mejs-sourcechooser-selector input,.mejs__sourcechooser-selector input{clear:both;float:left;margin:3px 3px 0 0}.mejs-sourcechooser-selector label,.mejs__sourcechooser-selector label{display:inline-block;float:left;font-size:12px;line-height:15px;padding:4px 0 0;width:100px}
--------------------------------------------------------------------------------
/dist/speed/speed-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.speed-rate'] = 'Velocitat';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.speed-rate'] = 'Rychlost';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.speed-rate'] = 'Geschwindigkeitsrate';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.speed-rate'] = 'Velocidad';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.speed-rate'] = 'نرخ سرعت';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.speed-rate'] = 'Vitesse';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.speed-rate'] = 'Brzina reprodukcije';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.speed-rate'] = 'Sebesség';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.speed-rate'] = 'Velocità';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.speed-rate'] = '高速';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.speed-rate'] = '속도 속도';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.speed-rate'] = 'Kelajuan';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.speed-rate'] = 'Snelheidsgraad';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.speed-rate'] = 'Prędkość';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.speed-rate'] = 'Taxa de velocidade';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.speed-rate'] = 'Viteză de viteză';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.speed-rate'] = 'Скорость воспроизведения';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.speed-rate'] = 'Rýchlosť';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.speed-rate'] = 'Hastighet';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.speed-rate'] = 'Hız oranı';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.speed-rate'] = 'Швидкість відтворення';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.speed-rate'] = '速度';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.speed-rate'] = '速度';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/speed/speed.css:
--------------------------------------------------------------------------------
1 | .mejs__speed-button,
2 | .mejs-speed-button {
3 | position: relative;
4 | }
5 |
6 | .mejs__speed-button > button,
7 | .mejs-speed-button > button {
8 | background: transparent;
9 | color: #fff;
10 | font-size: 11px;
11 | line-height: normal;
12 | margin: 11px 0 0;
13 | width: 36px;
14 | }
15 |
16 | .mejs__speed-selector,
17 | .mejs-speed-selector {
18 | background: rgba(50, 50, 50, 0.7);
19 | border: solid 1px transparent;
20 | border-radius: 0;
21 | height: 150px;
22 | left: -10px;
23 | overflow: hidden;
24 | padding: 0;
25 | position: absolute;
26 | top: -100px;
27 | visibility: hidden;
28 | width: 60px;
29 | }
30 |
31 | .mejs__speed-selector,
32 | .mejs-speed-selector {
33 | visibility: visible;
34 | }
35 |
36 | .mejs__speed-selector-list,
37 | .mejs-speed-selector-list {
38 | display: block;
39 | list-style-type: none !important;
40 | margin: 0;
41 | overflow: hidden;
42 | padding: 0;
43 | }
44 |
45 | .mejs__speed-selector-list-item,
46 | .mejs-speed-selector-list-item {
47 | color: #fff;
48 | display: block;
49 | list-style-type: none !important;
50 | margin: 0 0 6px;
51 | overflow: hidden;
52 | padding: 0 10px;
53 | }
54 |
55 | .mejs__speed-selector-list-item:hover,
56 | .mejs-speed-selector-list-item:hover {
57 | background-color: rgb(200, 200, 200) !important;
58 | background-color: rgba(255, 255, 255, 0.4) !important;
59 | }
60 |
61 | .mejs__speed-selector-input,
62 | .mejs-speed-selector-input {
63 | clear: both;
64 | float: left;
65 | left: -1000px;
66 | margin: 3px 3px 0 5px;
67 | position: absolute;
68 | }
69 |
70 | .mejs__speed-selector-label,
71 | .mejs-speed-selector-label {
72 | color: white;
73 | cursor: pointer;
74 | float: left;
75 | font-size: 11px;
76 | line-height: 15px;
77 | margin-left: 5px;
78 | padding: 4px 0 0;
79 | width: 60px;
80 | }
81 |
82 | .mejs__speed-selected,
83 | .mejs-speed-selected {
84 | color: rgba(33, 248, 248, 1);
85 | }
86 |
87 | .mejs__speed-selector,
88 | .mejs-speed-selector {
89 | visibility: hidden;
90 | }
91 | .mejs__speed-button:hover .mejs__speed-selector,
92 | .mejs-speed-button:hover .mejs-speed-selector {
93 | visibility: visible;
94 | }
95 |
--------------------------------------------------------------------------------
/dist/speed/speed.min.css:
--------------------------------------------------------------------------------
1 | .mejs-speed-button,.mejs__speed-button{position:relative}.mejs-speed-button>button,.mejs__speed-button>button{background:transparent;color:#fff;font-size:11px;line-height:normal;margin:11px 0 0;width:36px}.mejs-speed-selector,.mejs__speed-selector{background:rgba(50,50,50,.7);border:1px solid transparent;border-radius:0;height:150px;left:-10px;overflow:hidden;padding:0;position:absolute;top:-100px;width:60px;visibility:visible}.mejs-speed-selector-list,.mejs__speed-selector-list{display:block;list-style-type:none!important;margin:0;overflow:hidden;padding:0}.mejs-speed-selector-list-item,.mejs__speed-selector-list-item{color:#fff;display:block;list-style-type:none!important;margin:0 0 6px;overflow:hidden;padding:0 10px}.mejs-speed-selector-list-item:hover,.mejs__speed-selector-list-item:hover{background-color:#c8c8c8!important;background-color:hsla(0,0%,100%,.4)!important}.mejs-speed-selector-input,.mejs__speed-selector-input{clear:both;float:left;left:-1000px;margin:3px 3px 0 5px;position:absolute}.mejs-speed-selector-label,.mejs__speed-selector-label{color:#fff;cursor:pointer;float:left;font-size:11px;line-height:15px;margin-left:5px;padding:4px 0 0;width:60px}.mejs-speed-selected,.mejs__speed-selected{color:#21f8f8}.mejs-speed-selector,.mejs__speed-selector{visibility:hidden}.mejs-speed-button:hover .mejs-speed-selector,.mejs__speed-button:hover .mejs__speed-selector{visibility:visible}
--------------------------------------------------------------------------------
/dist/stop/stop-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.stop'] = 'Aturar';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.stop'] = 'Stop';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.stop'] = 'Stop';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.stop'] = 'Parar';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.stop'] = 'متوقف کردن';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.stop'] = 'Stop';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.stop'] = 'Zaustavi';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.stop'] = 'Állj meg';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.stop'] = 'Stop';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.stop'] = '止';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.stop'] = '중지';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.stop'] = 'Berhenti';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.stop'] = 'Hou op';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.stop'] = 'Zatrzymaj';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.stop'] = 'Pare';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.stop'] = 'Stop';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.stop'] = 'Остановить';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.stop'] = 'Prestať';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.stop'] = 'Stoppa';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.stop'] = 'Durdur';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.stop'] = 'Зупинити';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.stop'] = '停止';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.stop'] = '停止';
71 | }
72 |
--------------------------------------------------------------------------------
/dist/stop/stop.css:
--------------------------------------------------------------------------------
1 | .mejs__stop > button,
2 | .mejs-stop > button {
3 | background: url('stop.svg') 0 2px no-repeat;
4 | }
5 |
--------------------------------------------------------------------------------
/dist/stop/stop.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i';
28 |
29 | t.addControlElement(button, 'stop');
30 |
31 | button.addEventListener('click', function () {
32 | if (typeof media.stop === 'function') {
33 | media.stop();
34 | } else if (media.readyState > 0) {
35 | if (!media.paused) {
36 | media.pause();
37 | }
38 |
39 | media.setSrc('');
40 | media.load();
41 |
42 | var playButton = controls.querySelector('.' + t.options.classPrefix + 'playpause-button');
43 | mejs.Utils.removeClass(playButton, t.options.classPrefix + 'pause');
44 | mejs.Utils.addClass(playButton, t.options.classPrefix + 'play');
45 |
46 | if (t.container.querySelector('.' + t.options.classPrefix + 'cannotplay')) {
47 | t.container.querySelector('.' + t.options.classPrefix + 'cannotplay').remove();
48 | layers.querySelector('.' + t.options.classPrefix + 'overlay-error').parentNode.style.display = 'none';
49 | layers.querySelector('.' + t.options.classPrefix + 'overlay-error').remove();
50 | }
51 | }
52 |
53 | var event = mejs.Utils.createEvent('timeupdate', media);
54 | media.dispatchEvent(event);
55 | });
56 | }
57 | });
58 |
59 | },{}]},{},[1]);
60 |
--------------------------------------------------------------------------------
/dist/stop/stop.min.css:
--------------------------------------------------------------------------------
1 | .mejs-stop>button,.mejs__stop>button{background:url(stop.svg) 0 2px no-repeat}
--------------------------------------------------------------------------------
/dist/stop/stop.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
12 | !function n(i,a,l){function p(t,e){if(!a[t]){if(!i[t]){var o="function"==typeof require&&require;if(!e&&o)return o(t,!0);if(c)return c(t,!0);var s=new Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}var r=a[t]={exports:{}};i[t][0].call(r.exports,function(e){return p(i[t][1][e]||e)},r,r.exports,n,i,a,l)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e',n.addControlElement(i,"stop"),i.addEventListener("click",function(){if("function"==typeof r.stop)r.stop();else if(04
2 |
--------------------------------------------------------------------------------
/dist/vrview/cardboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/dist/vrview/cardboard.png
--------------------------------------------------------------------------------
/dist/vrview/cardboard.svg:
--------------------------------------------------------------------------------
1 | 6
--------------------------------------------------------------------------------
/dist/vrview/vrview.css:
--------------------------------------------------------------------------------
1 | .mejs__vrview-button > button,
2 | .mejs-vrview-button > button {
3 | background: url('cardboard.svg') no-repeat 0 4px;
4 | }
--------------------------------------------------------------------------------
/dist/vrview/vrview.min.css:
--------------------------------------------------------------------------------
1 | .mejs-vrview-button>button,.mejs__vrview-button>button{background:url(cardboard.svg) no-repeat 0 4px}
--------------------------------------------------------------------------------
/docs/a11y.md:
--------------------------------------------------------------------------------
1 | # Accessibility
2 |
3 | ## Overview
4 | This plugin enables special accessibility features for adding an audio description or sign language annotated movie file.
5 |
6 | ## Keyword to use it
7 | ```javascript
8 | features: [..., 'a11y']
9 | ```
10 |
11 | ## API
12 | Parameter | Type | Default | Description
13 | ------ | --------- | ------- | --------
14 | `data-video-description` | array | null | An array of video source objects like `{ src: "description.mp4", type: "video/mp4" }`. This plugin will evaluate the best matching type out of the array.
15 | `data-audio-description` | array | null | An array of audio description source objects like `{ src: "description.mp3", type: "audio/mp3" }`. This plugin will evaluate the best matching type out of the array.
16 | `data-audio-description-voiceover` | boolean | false | If set as data attribute only or with value `true` audio description will be started in voice-over mode.
17 | `iconSpritePathA11y` | string | `mejs-a11y-icons.svg` | Path for the SVG icon sprite file.
18 |
19 | #### Audio-description node
20 | The Audio description node is bound to the MediaElement.js object at `mejs.audioDescription.node`, like the original node is bound under `mejs.node`.
21 |
22 | ## Icons
23 | The sign language and audio description icon were made by [Font Awesome](https://fontawesome.com) and underlie the following [License](https://fontawesome.com/license).
24 |
25 | ---
26 |
27 | This Plugin is sponsored by [Aktion Mensch e.V.](https://www.aktion-mensch.de)
28 |
29 | ---
30 |
31 | ## German Translation
32 |
33 | ### Übersicht
34 | Dieses Plugin ermöglicht besondere Barrierefreiheit-Erweiterungen zum Hinzufügen von Audio-Deskription oder Videos mit Übersetzung in Gebärdensprache.
35 |
36 | ### Keyword zum Einbinden
37 | ```javascript
38 | features: [..., 'a11y']
39 | ```
40 |
41 | ### API
42 | Parameter | Type | Default | Beschreibung
43 | ------ | --------- | ------- | --------
44 | `data-video-description` | array | null | Ein Array von Gebärden-Sprachen-Video-Source Objekten, die wie folgt auszusehen haben: `{ src: "description.mp4", type: "video/mp4" }`. Das Plugin wählt die am besten passende Video-Source aus dem Array aus.
45 | `data-audio-description` | array | null | Ein Array von Audio-Deskription-Source Objekten, die wie folgt auszusehen haben: `{ src: "description.mp3", type: "audio/mp3" }`. Das Plugin wählt die am besten passende Audio-Source aus dem Array aus.
46 | `data-audio-description-voiceover` | boolean | false | Wenn der Parameter als Data-Attribut gesetzt oder mit dem Wert `true` belegt ist, wird die Audio-Deskription als Voice-Over gestartet.
47 |
48 | ##### Audio-Deskription Node
49 | Der Audio-Deskription Node wird im MediaElement.js Objekt unter `mejs.audioDescription.node` eingebunden, so wie der eigentliche Node unter `mejs.node` eingebunden ist.
50 |
51 | ### Icons
52 | Das Gebärdensprache- und Audio-Deskriptions-Icon stammen von [Font Awesome](https://fontawesome.com) und unterliegen der folgenden [Lizenz](https://fontawesome.com/license).
53 |
54 |
55 | ---
56 |
57 | Dieses Plugin wurde gesponsert von [Aktion Mensch e.V.](https://www.aktion-mensch.de)
58 |
--------------------------------------------------------------------------------
/docs/ads-vast.md:
--------------------------------------------------------------------------------
1 | # VAST/VPAID
2 |
3 | ## Overview
4 |
5 | This plugin, with the [Ads](ads.md) plugin, manages the displaying of Ads before media starts playing.
6 |
7 | It will generate the proper structures after parsing VPAID/VAST XML files to be processed by the `Ads` plugin.
8 |
9 | **NOTE**: Currently, this plugin only supports Linear elements with MP4/FLV. Support for Flash and Javascript MediaFiles coming soon.
10 |
11 | ## Keyword to use it
12 | ```javascript
13 | features: [..., 'vast']
14 | ```
15 |
16 | ## API
17 |
18 | Parameter | Type | Default | Description
19 | ------ | --------- | ------- | --------
20 | vastAdTagUrl | string | __empty__ | VAST or VPAID URL
21 | vastAdsType | string | `vast` | Type of Ads (`vast` or `vpaid`)
--------------------------------------------------------------------------------
/docs/ads.md:
--------------------------------------------------------------------------------
1 | # Ads
2 |
3 | ## Overview
4 |
5 | This plugin, with the [VAST/VPAID](ads-vast.md) plugin, manages the displaying of Ads before media starts playing.
6 |
7 | It will fire the proper events depending of the nature of the Ads type (`vast` or `vpaid`) and takes care of the manipulation
8 | of the user's experience in general.
9 |
10 | ## Keyword to use it
11 | ```javascript
12 | features: [..., 'ads']
13 | ```
14 |
15 | ## API
16 |
17 | Parameter | Type | Default | Description
18 | ------ | --------- | ------- | --------
19 | adsPrerollMediaUrl | array | `[]` | Collection of Ads URLs
20 | adsPrerollAdUrl | array | `[]` | Collection of URLs that will be tracked through a click event when playing an Ad
21 | adsPrerollAdEnableSkip | boolean | `false` | If true, allows user to skip the pre-roll ad
22 | adsPrerollAdSkipSeconds | number | `-1` | If positive number entered, it will only allow skipping after the time has elasped
23 | indexPreroll | number | `0` | Keep track of the index for the preroll ads to be able to show more than one preroll
24 |
--------------------------------------------------------------------------------
/docs/airplay.md:
--------------------------------------------------------------------------------
1 | # AirPlay
2 |
3 | ## Overview
4 |
5 | This plugin displays a button to interact with an AirPlay device, if available.
6 |
7 | It detects if media tag has the `x-webkit-airplay` attribute set as `allow`; if not, the plugin sets it, to provide also native support.
8 |
9 | ## Keyword to use it
10 | ```javascript
11 | features: [..., 'airplay']
12 | ```
13 |
14 | ## API
15 |
16 | Parameter | Type | Default | Description
17 | ------ | --------- | ------- | --------
18 | airPlayTitle | string | `null` | AirPlay button title for ARIA purposes
--------------------------------------------------------------------------------
/docs/chromecast.md:
--------------------------------------------------------------------------------
1 | # Chromecast
2 |
3 | ## Overview
4 |
5 | This plugin uses version 3.2 to take advantage of [Google Cast Framework](https://developers.google.com/cast/docs/developers), and creates a button to start/stop streaming.
6 |
7 | In order to get the most of this plugin, some elements must be placed in the video tag.
8 |
9 | The following snippet shows the `data-cast-*` attributes needed to achieve Chromecast best experience, **even when they are not required**.
10 |
11 | ```html
12 |
16 |
17 |
18 |
19 |
23 |
24 |
25 | ```
26 |
27 | The `poster` or `data-cast-poster` attributes are not required as well, but most of the media players use a static image when media is being broadcast in Chromecast,
28 | so **it is recommended their use**.
29 |
30 | `data-cast-poster` is meant for **audio only** since `poster` is not supported natively for audio tag.
31 |
32 | Chromecast **ONLY** accepts **MP4, HLS and M(PEG)-DASH** formats.
33 |
34 | Also, a page can contain **ONLY ONE** sender; otherwise, an error indicating that `cast-button` has been registered will be logged.
35 |
36 | To avoid that, [this link](https://jsfiddle.net/Luuwnjfm/24/) shows a way to get away with it if you have to render your player dynamically.
37 |
38 | ## Keyword to use it
39 | ```javascript
40 | features: [..., 'chromecast']
41 | ```
42 |
43 | ## API
44 |
45 | Parameter | Type | Default | Description
46 | ------ | --------- | ------- | --------
47 | castTitle | string | `null` | Chromecast button title for WARIA purposes
48 | castAppId | string | `null` | Chromecast Application ID; if `null` is provided, it will default to `chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID`
49 | castPolicy | string | `origin` | Chromecast default policy: `origin` (by default, auto connect from same appId and page origin), `tab` (auto connect from same appId, page origin, and tab) and `page` (no auto connect)
50 | castEnableTracks | boolean | `false` | Whether to load tracks or not through Chromecast. In order to process tracks correctly, `tracks` feature must be enable on the player configuration and CORS **MUST** be setup correctly. Read [this link](https://developers.google.com/cast/docs/player) for more information
51 | castIsLive | boolean | `false` | Whether the current media is a live stream or not
--------------------------------------------------------------------------------
/docs/context-menu.md:
--------------------------------------------------------------------------------
1 | # Context Menu
2 |
3 | ## Overview
4 |
5 | This plugin disabled the default context menu, and generates a custom one when performing mouse left click.
6 |
7 | By default, it creates the following actions:
8 |
9 | * Turn on/off fullscreen
10 | * Turn on/off mute
11 | * Download media
12 |
13 | ## Keyword to use it
14 | ```javascript
15 | features: [..., 'contextmenu']
16 | ```
17 |
18 | ## API
19 |
20 | Parameter | Type | Default | Description
21 | ------ | --------- | ------- | --------
22 | contextMenuItems | array | `[]` | An array of objects with format `{ render (player) { }, click (player) {} }` to render and perform click menu items, or `{ isSeparator: true }` to separate items
--------------------------------------------------------------------------------
/docs/facebook-pixel.md:
--------------------------------------------------------------------------------
1 | # Facebook Pixel
2 |
3 | ## Overview
4 |
5 | This plugin enables [Facebook Pixel](https://developers.facebook.com/docs/facebook-pixel) to send certain events, such as play, pause, ended, etc.
6 |
7 | It requires previous configuration on Pixel to send events properly.
8 |
9 | ## Keyword to use it
10 | ```javascript
11 | features: [..., 'facebookpixel']
12 | ```
13 |
14 | ## API
15 |
16 | Parameter | Type | Default | Description
17 | ------ | --------- | ------- | --------
18 | facebookPixelTitle | string | __empty__ | The title to record events through Facebook Pixel (like Google Analytics)
19 | facebookPixelCategory | string | `Videos` | The category name to record events through Facebook Pixel (like Google Analytics)
--------------------------------------------------------------------------------
/docs/google-analytics.md:
--------------------------------------------------------------------------------
1 | # Google Analytics
2 |
3 | ## Overview
4 |
5 | This plugin enables [Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/events)
6 | to send media events, such as `play`, `pause`, `ended`, etc.
7 |
8 | It requires Google Analytics configuration to send events properly. For more information, check
9 | [Set up Analytics tracking](https://support.google.com/analytics/answer/1008080?hl=en).
10 |
11 | ## Keyword to use it
12 | ```javascript
13 | features: [..., 'googleanalytics']
14 | ```
15 |
16 | ## API
17 |
18 | Parameter | Type | Default | Description
19 | ------ | --------- | ------- | --------
20 | googleAnalyticsTitle | string | _(empty)_ | Google Analytics Title,
21 | googleAnalyticsCategory | string | `Videos` | Google Analytics Category label,
22 | googleAnalyticsEventPlay | string | `Play` | Google Analytics Play label
23 | googleAnalyticsEventPause | string | `Pause` | Google Analytics Pause label
24 | googleAnalyticsEventEnded | string | `Ended` | Google Analytics ended event label
25 | googleAnalyticsEventTime | string | `Time` | Google Analytics time event label
--------------------------------------------------------------------------------
/docs/google-tag-manager.md:
--------------------------------------------------------------------------------
1 | # Google Tag Manager
2 |
3 | ## Overview
4 |
5 | This plugin enables [Google Tag Manager](https://support.google.com/tagmanager/answer/6106961?hl=en)
6 | to push dataLayer events, such as `play`, `pause`, `ended`, etc.
7 |
8 | It requires Google Tag Manager configuration to send events properly. For more information, check
9 | [Set up GTM triggers](https://support.google.com/tagmanager/answer/6102821?hl=en).
10 |
11 | ## Keyword to use it
12 | ```javascript
13 | features: [..., 'googletagmanager']
14 | ```
15 |
16 | ## API
17 |
18 | Parameter | Type | Default | Description
19 | ------ | --------- | ------- | --------
20 | Play | string | `clickPlay` | Google Tag Manager Play Event,
21 | Pause | string | `clickPause` | Google Tag Manager Pause Event
22 | Ended | string | `clickEnded` | Google Tag Manager Ended Event
23 |
--------------------------------------------------------------------------------
/docs/jump-forward.md:
--------------------------------------------------------------------------------
1 | # Jump Forward
2 |
3 | ## Overview
4 |
5 | This plugin creates a button to forward media a specific number of seconds.
6 |
7 | It will work even when media is not being played initially.
8 |
9 | ## Keyword to use it
10 | ```javascript
11 | features: [..., 'jumpforward']
12 | ```
13 |
14 | ## API
15 |
16 | Parameter | Type | Default | Description
17 | ------ | --------- | ------- | --------
18 | jumpForwardInterval | number | `30` | Seconds to jump forward media
19 | jumpForwardText | string | `null` | Title for Jump Forward button for WARIA purposes
20 | iconSpritePathJumpForward | string | `mejs-jump-forward.svg` | Path for the SVG icon sprite file.
21 |
--------------------------------------------------------------------------------
/docs/loop.md:
--------------------------------------------------------------------------------
1 | # Loop
2 |
3 | ## Overview
4 |
5 | This plugin creates a loop button in the control bar to turn on/off the loop effect. If activated, it will restart media once it finishes.
6 |
7 | This button mimics the HTML5's `loop` attribute in the `video`/`audio` tags.
8 |
9 | ## Keyword to use it
10 | ```javascript
11 | features: [..., 'loop']
12 | ```
13 |
14 | ## API
15 |
16 | Parameter | Type | Default | Description
17 | ------ | --------- | ------- | --------
18 | loopText | string | `null` | Title for Loop button for WARIA purposes when loop feature is activated
--------------------------------------------------------------------------------
/docs/markers.md:
--------------------------------------------------------------------------------
1 | # Markers
2 |
3 | ## Overview
4 |
5 | This plugin allows you to create Visual Cues in the progress time rail.
6 |
7 | Also, allows you to register a custom callback function that will be triggered every time the media reaches a marker.
8 |
9 | The `MediaElementPlayer` object and media's current time should be passed to the registered callback function.
10 |
11 | The marker color is configurable.
12 |
13 | ## Keyword to use it
14 | ```javascript
15 | features: [..., 'markers']
16 | ```
17 |
18 | ## API
19 |
20 | Parameter | Type | Default | Description
21 | ------ | --------- | ------- | --------
22 | markerColor | string | `#E9BC3D` | Specify the color of marker in hexadecimal code
23 | markerWidth | number | `1` | Specify the width of marker in pixels
24 | markers | array | `[]` | List of numbers to specify marker times in seconds
25 | markerCallback | function | `function(media, time) {}` | Callback function invoked when a marker position is reached
--------------------------------------------------------------------------------
/docs/markersrolls.md:
--------------------------------------------------------------------------------
1 | # Markers
2 |
3 | ## Overview
4 |
5 | Based in Markers and Postroll plugins.
6 |
7 | This plugin allows you to create Visual Cues in the progress time rail and inject HTML content in these markers.
8 | The HTML content will be displayed every time the media reaches a marker.
9 |
10 | Every marker answer to a URL to inject the content in the video player when the marker position is reached.
11 |
12 | Color for markers are configurable.
13 |
14 | ## Keyword to use it
15 | ```javascript
16 | features: [..., 'markersrolls']
17 | ```
18 |
19 | ## API
20 |
21 | Parameter | Type | Default | Description
22 | ------ | --------- | ------- | --------
23 | markersRollsColor | string | `#E9BC3D` | Specify the color of markers in hexadecimal code
24 | markersRollsWidth | number | `1` | Specify the width of markers in pixels
25 | markersRolls | object | `{}` | Marker times in seconds associated to the URL to inject. See demo folder for examples.
26 |
--------------------------------------------------------------------------------
/docs/picture-in-picture.md:
--------------------------------------------------------------------------------
1 | # Picture in Picture
2 |
3 | ## Overview
4 |
5 | This feature allows you to view a video outside of the browsers viewport.
6 | Also know as **Picture-In-Picture** or PiP
7 |
8 | ## Note
9 |
10 | + This is not a W3C standard though it supported by chrome (70 or later) and Safari (10 or later)
11 |
12 |
13 | ## Keyword
14 |
15 | ```javascript
16 | $("video").mediaelementplayer({
17 | features: [..., 'pictureInPicture']
18 | });
19 | ```
20 |
21 | ## API
22 |
23 | Parameter | Type | Default | Description
24 | ------ | ------ | ------ | ------
25 | PiPTitle |string |`null` |alternative button title
26 |
--------------------------------------------------------------------------------
/docs/playlist.md:
--------------------------------------------------------------------------------
1 | # Playlist
2 |
3 | ## Overview
4 |
5 | This plugin allows the creation of a video/audio playlist.
6 |
7 | The following table described the components that can be used with this plugin, and the keyword to be used on the `features` array configuration.
8 |
9 | Component | Keyword | Description
10 | --------- | ------- | ---------------
11 | Playlist | `playlist` | REQUIRED; The main plugin that builds the playlist
12 | Previous Track | `prevtrack` | OPTIONAL; Control to go to the previous playlist item
13 | Next Track | `nexttrack` | OPTIONAL; Control to go to the next playlist item
14 | Loop | `loop` | OPTIONAL; Control to loop the current media
15 | Shuffle | `shuffle` | OPTIONAL; Control to shuffle the playlist
16 |
17 | **NOTE:** If you plan to use Loop, it is strongly recommended NOT to use the standalone version of Loop included in the project.
18 |
19 | ## Keyword to use it
20 | ```javascript
21 | features: [..., 'playlist', 'nexttrack', 'prevtrack', 'shuffle', 'loop']
22 | ```
23 |
24 | ## API
25 |
26 | Parameter | Type | Default | Description
27 | ------ | --------- | ------- | --------
28 | playlist | array | `[]` | List to be played; the array consists in a series of objects that MUST include the `src` and `title` attributes; other possible items: `data-playlist-thumbnail`, `type`, `description`. **If its empty, it will search for all the `source` elements within the video/audio tags**
29 | showPlaylist | boolean | `true` | Whether or not to display the playlist; if so, a button to toggle the playlist will be displayed
30 | autoClosePlaylist | boolean | `false` | If set to `true`, the playlist container will hide once user selects an item
31 | prevText | string | `null` | Title for Previous button for WARIA purposes
32 | nextText | string | `null` | Title for Next button for WARIA purposes
33 | loopText | string | `null` | Title for Loop button for WARIA purposes
34 | shuffleText | string | `null` | Title for Shuffle button for WARIA purposes
35 | playlistTitle | string | `null` | Title for Playlist button for WARIA purposes
36 | currentMessage | string | `null` | Message ONLY for audio, prepended to the `title` of media (i.e., _Now playing_)
37 |
--------------------------------------------------------------------------------
/docs/postroll.md:
--------------------------------------------------------------------------------
1 | # Postroll
2 |
3 | ## Overview
4 |
5 | This plugin allows the injection of any HTML content in an independent layer once the media has ended.
6 |
7 | The following snippet shows the proper HTML to activate the postroll functionality.
8 |
9 | ```html
10 |
11 |
12 |
13 |
14 | ```
15 |
16 | The `link` tag's `rel` attribute **must be `postroll` always**.
17 |
18 | ## Keyword to use it
19 | ```javascript
20 | features: [..., 'postroll']
21 | ```
22 |
23 | ## API
24 |
25 | Parameter | Type | Default | Description
26 | ------ | --------- | ------- | --------
27 | postrollCloseText | string | `null` | Title for button to Postroll layer for WARIA purposes
--------------------------------------------------------------------------------
/docs/preview.md:
--------------------------------------------------------------------------------
1 | # Preview
2 |
3 | ## Overview
4 |
5 | This plugin allows the creation of a preview effect on videos: playing on hover and with possibility of mute/fade-in/fade-out its audio.
6 |
7 | ## Keyword to use it
8 | ```javascript
9 | features: [..., 'preview']
10 | ```
11 |
12 | ## API
13 |
14 | Parameter | Type | Default | Description
15 | ------ | --------- | ------- | --------
16 | previewMode | boolean | `false` | Media starts playing when users mouse hovers on it, and resets when leaving player area
17 | muteOnPreviewMode | boolean | `true` | When playing in preview mode, turn on/off sound
18 | fadeInAudioStart | number | `0` | If `fadeInAudioInterval` is set, time when it starts fading in
19 | fadeInAudioInterval | number | `0` | When playing media, time interval to fade in audio (must be greater than zero)
20 | fadeOutAudioStart | number | `0` | If `fadeOutAudioInterval` is set, time when it starts fading out
21 | fadeOutAudioInterval | number | `0` | When playing media, time interval to fade out audio (must be greater than zero)
22 | fadePercent | number | `0.2` | Percentage in which media will fade in/out (in decimals, where 0.2 = 20%, 1 = 100%)
23 | pauseOnlyOnPreview | boolean | `false` | Whether reset or not the media when on preview mode
24 | delayPreview | number | `0` | Delay in milliseconds to start previewing media
--------------------------------------------------------------------------------
/docs/quality.md:
--------------------------------------------------------------------------------
1 | # Quality
2 |
3 | ## Overview
4 |
5 | This plugin allows the generation of a menu with different video/audio qualities, depending of the elements set
6 | in the tags, such as `title` and `data-quality`
7 |
8 | ## Keyword to use it
9 | ```javascript
10 | features: [..., 'quality']
11 | ```
12 |
13 | ## API
14 |
15 | Parameter | Type | Default | Description
16 | ------ | --------- | ------- | --------
17 | defaultQuality | string | `null` | Initial media quality; if `null`, it will take the first available source
18 | qualityText | string | `null` | Title for Quality button for WARIA purposes
19 | qualityChangeCallback | callback | | Action that will be executed as soon as the user change video quality; passes 3 arguments: media (the wrapper that mimics all the native events/properties/methods for all renderers), node (the original HTML video, audio or iframe tag where the media was loaded originally and string newQuality
20 | iconPathQuality | string | `mejs-quality-icon.svg` | Path for the SVG icon file
--------------------------------------------------------------------------------
/docs/skip-back.md:
--------------------------------------------------------------------------------
1 | # Skip Back
2 |
3 | ## Overview
4 |
5 | This plugin creates a button to rewind media a specific number of seconds.
6 |
7 | It will work even when media is not being played initially.
8 |
9 | ## Keyword to use it
10 | ```javascript
11 | features: [..., 'skipback']
12 | ```
13 |
14 | ## API
15 |
16 | Parameter | Type | Default | Description
17 | ------ | --------- | ------- | --------
18 | skipBackInterval | number | `30` | Seconds to skip back media
19 | skipBackText | string | `null` | Title for Skip Back button for WARIA purposes
20 | iconSpritePathSkipBack | string | `mejs-skip-back.svg` | Path for the SVG icon sprite file.
21 |
--------------------------------------------------------------------------------
/docs/snapshot.md:
--------------------------------------------------------------------------------
1 | # Mediaelement Snapshot
2 |
3 | * Author: Yassine Qoraiche
4 | * Website: https://codecsocean.com/
5 | * License: MIT
6 |
7 | ## Overview
8 |
9 | Mediaelement Snapshot plugin creates a button in the player controls allows to take video snapshots with different image types (jpeg, png).
10 |
11 | ## Installation
12 |
13 | Download plugin files and place the js files after the main [Mediaelement](https://github.com/mediaelement/mediaelement/) player js `mediaelement-and-player.min.js` file:
14 |
15 | ```HTML
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ```
24 | Place plugin main CSS style after the main player stylesheet
25 |
26 | ```HTML
27 |
28 |
29 |
30 |
31 |
32 |
33 | ```
34 |
35 | Add plugin keyword to the features list
36 |
37 | ```Javascript
38 | features: [..., 'snapshot']
39 | ```
40 |
41 | That's it !.
42 |
43 | For more details about [How to Install mediaelement plugin](https://github.com/mediaelement/mediaelement-plugins#installation).
44 |
45 | ## Usage
46 |
47 | Initialize Snapshot plugin
48 |
49 | ```Javascript
50 |
51 | var player = new MediaElementPlayer(document.querySelector('video'), {
52 |
53 | features:['play', 'playpause', volume', 'progress', 'snapshot', fullscreen'],
54 |
55 | snapType:'jpeg',
56 | snapQuality: 0.5, //half quality
57 | snapShot: true,
58 |
59 | snapSuccess: function(snap){
60 | console.log(snap.url); //return snap object
61 | },
62 |
63 | snapError: function(){
64 | console.log('you can not take snapshot while the player loading !');
65 | }
66 |
67 | });
68 |
69 | ```
70 |
71 | ## API
72 |
73 | | Parameter | Type | Default | Description |
74 | | ----------- | -------------- | --------| -----------
75 | | snapShot | boolean | `true` | Either to save snapshot image locally (`true`) or not (`false`)
76 | | snapType | string | `png` | Type of image `png`or `jpeg`
77 | | snapWidth | number | Default video width | Snapshot image width
78 | | snapHeight | number | Default video height | Snapshot image height
79 | | snapQuality | number or float | `1` | Snapshot image quality between `0` and `1`
80 | | snapSuccess | function() | `null` | success callback => (snapshot) accepts one parameter contains snapshot object
81 | | snapError | function() | `null` | error callback() => () accepts no parameters
82 |
83 | ## Support
84 |
85 | Having trouble with this plugin? [create an issue](https://github.com/Codecsocean/mediaelement-snapshot/issues) describing the problem that you have encountered.
86 |
87 |
--------------------------------------------------------------------------------
/docs/source-chooser.md:
--------------------------------------------------------------------------------
1 | # Source Chooser
2 |
3 | ## Overview
4 |
5 | This plugin generates a button to choose between different sources, if more than one is indicated within the `video`/`audio` tags.
6 |
7 | ```html
8 |
9 |
10 |
11 |
12 |
13 | ```
14 |
15 | ## Keyword to use it
16 | ```javascript
17 | features: [..., 'sourcechooser']
18 | ```
19 |
20 | ## API
21 |
22 | Parameter | Type | Default | Description
23 | ------ | --------- | ------- | --------
24 | sourcechooserText | string | `null` | Title for Source Chooser button for WARIA purposes
--------------------------------------------------------------------------------
/docs/speed.md:
--------------------------------------------------------------------------------
1 | # Speed
2 |
3 | ## Overview
4 |
5 | This plugin creates a button that allows the user to play media at different speed rates.
6 |
7 | ## Keyword to use it
8 | ```javascript
9 | features: [..., 'speed']
10 | ```
11 |
12 | ## API
13 |
14 | Parameter | Type | Default | Description
15 | ------ | --------- | ------- | --------
16 | speeds | array | `['1.50', '1.25', '1.00', '0.75']` | Enable speeding media; accounts for strings or objects like `[{name: 'Slow', value: '0.75'}, {name: 'Normal', value: '1.00'}, ...]`
17 | defaultSpeed | number | `1.00` | Initial speed of media
18 | speedChar | string | `x` | Character used to stop speeding media
19 | speedText | string | `null` | Title for Speed button for WARIA purposes
--------------------------------------------------------------------------------
/docs/stop.md:
--------------------------------------------------------------------------------
1 | # Stop
2 |
3 | ## Overview
4 |
5 | This plugin enables a Stop button in the control bar, which basically pauses media and loads an empty source. Once this is done, user
6 | must implement his own mechanism to resume since the reference to the original source will get lost.
7 |
8 | If a `stop` method is detected, the button will fire its functionality.
9 |
10 | ## Keyword to use it
11 | ```javascript
12 | features: [..., 'stop']
13 | ```
14 |
15 | ## API
16 |
17 | Parameter | Type | Default | Description
18 | ------ | --------- | ------- | --------
19 | stopText | string | `null` | Title for Stop button for WARIA purposes
--------------------------------------------------------------------------------
/docs/vrview.md:
--------------------------------------------------------------------------------
1 | # VRView
2 |
3 | ## Overview
4 |
5 | This plugin allows the interaction of [Google's VRView](https://developers.google.com/vr/concepts/vrview-web) with `MediaElement.js` to see 360 videos.
6 |
7 | Google VRView only supports MP4, M(PEG)-DASH and HLS videos.
8 |
9 | ## API
10 |
11 | Parameter | Type | Default | Description
12 | ------ | --------- | ------- | --------
13 | vrPath | string | _empty_ | Path to load Google VRView library; by default, it will try to load `https://storage.googleapis.com/vrview/2.0/build/vrview.min.js`
14 | vrIsStereo | boolean | `true` | Indicates whether the content at the image or video URL is stereo or not
15 | vrIsAutopanOff | boolean | `true` | When true, disables the autopan introduction on desktop
16 | vrDebug | boolean | `false` | When `true`, turns on debug features like rendering hotspots ad showing the FPS meter
17 | vrDefaultYaw | number | `0` | Numeric angle in degrees of the initial heading for the 360° content. By default, the camera points at the center of the underlying image
18 | vrIsYawOnly | boolean | `false` | When `true`, prevents roll and pitch. This is intended for stereo panoramas
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mediaelement-plugins",
3 | "version": "5.0.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "https://github.com/mediaelement/mediaelement-plugins.git"
7 | },
8 | "bugs": {
9 | "url": "https://github.com/mediaelement/mediaelement-plugins/issues"
10 | },
11 | "private": false,
12 | "devDependencies": {
13 | "autoprefixer": "^6.7.7",
14 | "babel-cli": "^6.24.1",
15 | "babel-core": "^6.24.1",
16 | "babel-preset-env": "^1.5.0",
17 | "babel-register": "^6.24.1",
18 | "babelify": "^7.3.0",
19 | "browserify": "^13.1.1",
20 | "browserify-derequire": "^0.9.4",
21 | "bundle-collapser": "^1.2.1",
22 | "cssnano": "^3.8.0",
23 | "grunt": "^1.4.1",
24 | "grunt-babel": "^6.0.0",
25 | "grunt-browserify": "^5.0.0",
26 | "grunt-cli": "^0.1.13",
27 | "grunt-contrib-clean": "^1.1.0",
28 | "grunt-contrib-concat": "^1.0.1",
29 | "grunt-contrib-copy": "^1.0.0",
30 | "grunt-contrib-uglify": "^3.0.1",
31 | "grunt-contrib-watch": "^1.0.0",
32 | "grunt-eslint": "^19.0.0",
33 | "grunt-postcss": "^0.9.0",
34 | "grunt-remove-logging": "^0.2.0",
35 | "grunt-shell": "^2.1.0",
36 | "grunt-stylelint": "^0.8.0",
37 | "grunt-text-replace": "^0.4.0",
38 | "stylelint": "^7.10.1",
39 | "stylelint-order": "^0.4.4",
40 | "uglify-js": "^3.0.10"
41 | },
42 | "dependencies": {
43 | "global": "^4.3.1",
44 | "mediaelement": "^5.0.1"
45 | },
46 | "browserify": {
47 | "extensions": [
48 | ".js"
49 | ],
50 | "transform": [
51 | [
52 | "babelify",
53 | {
54 | "comments": false,
55 | "presets": [
56 | [
57 | "env",
58 | {
59 | "targets": {
60 | "browsers": [
61 | "last 5 versions",
62 | "ie > 10",
63 | "ios > 7",
64 | "android > 3"
65 | ]
66 | }
67 | }
68 | ]
69 | ]
70 | }
71 | ]
72 | ]
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/.DS_Store
--------------------------------------------------------------------------------
/src/a11y/a11y-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.de !== undefined) {
4 | mejs.i18n.de['mejs.a11y-audio-description'] = 'Audio Deskription An/Aus';
5 | mejs.i18n.de['mejs.a11y-video-description'] = 'Video Deskription An/Aus';
6 | }
7 |
8 | if (mejs.i18n.fr !== undefined) {
9 | mejs.i18n.fr['mejs.a11y-audio-description'] = 'Audio-description étendue On/Off';
10 | mejs.i18n.fr['mejs.a11y-video-description'] = 'Langue des signes On/Off';
11 | }
12 |
13 | if (mejs.i18n.nl !== undefined) {
14 | mejs.i18n.nl['mejs.a11y-audio-description'] = 'Audiobeschrijving Aan/Uit';
15 | mejs.i18n.nl['mejs.a11y-video-description'] = 'Gebarentaal Aan/Uit';
16 | }
17 |
18 | if (mejs.i18n.tr !== undefined) {
19 | mejs.i18n.tr['mejs.a11y-audio-description'] = 'Sesli betimleme değiştir';
20 | mejs.i18n.tr['mejs.a11y-video-description'] = 'Görüntülü betimleme değişti';
21 | }
22 |
--------------------------------------------------------------------------------
/src/a11y/a11y.css:
--------------------------------------------------------------------------------
1 | .mejs-volume-button.hidden,
2 | .mejs__volume-button.hidden {
3 | display: none;
4 | }
5 |
6 | .mejs-audio-description-player,
7 | .mejs__audio-description-player {
8 | display: none;
9 | }
10 |
--------------------------------------------------------------------------------
/src/a11y/audio-description-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/a11y/video-description-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/ads/ads.css:
--------------------------------------------------------------------------------
1 | .mejs__ads > a,
2 | .mejs-ads > a {
3 | display: block;
4 | height: 100%;
5 | position: absolute;
6 | right: 0;
7 | top: 0;
8 | width: 100%;
9 | }
10 | .mejs__ads-skip-block,
11 | .mejs-ads-skip-block {
12 | background: #000;
13 | background: rgba(0, 0, 0, 0.5);
14 | color: #fff;
15 | display: block;
16 | padding: 10px;
17 | position: absolute;
18 | right: 0;
19 | top: 0;
20 | }
21 | .mejs__ads-skip-button,
22 | .mejs-ads-skip-button {
23 | cursor: pointer;
24 | }
25 | .mejs__ads-skip-button:hover,
26 | .mejs-ads-skip-button:hover {
27 | text-decoration: underline;
28 | }
29 |
--------------------------------------------------------------------------------
/src/airplay/airplay.css:
--------------------------------------------------------------------------------
1 | .mejs__airplay-button > button,
2 | .mejs-airplay-button > button {
3 | background: url('airplay.svg') no-repeat 0 4px;
4 | }
5 |
6 | .mejs__airplay-button > button .fill,
7 | .mejs-airplay-button > button .fill {
8 | fill: #fff;
9 | }
10 |
11 | .mejs__airplay-button > button.active .fill,
12 | .mejs-airplay-button > button.active .fill {
13 | fill: #66a8cc;
14 | }
15 |
--------------------------------------------------------------------------------
/src/airplay/airplay.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Airplay button
5 | *
6 | * This feature creates an AirPlay button that enhances native AirPlay capabilities, if found
7 | */
8 |
9 | // Feature configuration
10 | Object.assign(mejs.MepDefaults, {
11 | /**
12 | * @type {?String}
13 | */
14 | airPlayText: null
15 | });
16 |
17 | Object.assign(MediaElementPlayer.prototype, {
18 | /**
19 | * Feature constructor.
20 | *
21 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
22 | */
23 | buildairplay () {
24 |
25 | // bail early if not available
26 | if (!window.WebKitPlaybackTargetAvailabilityEvent) {
27 | return;
28 | }
29 |
30 | const
31 | t = this,
32 | airPlayTitle = mejs.Utils.isString(t.options.airPlayText) ? t.options.airPlayText : 'AirPlay',
33 | button = document.createElement('div')
34 | ;
35 |
36 | button.className = `${t.options.classPrefix}button ${t.options.classPrefix}airplay-button`;
37 | button.innerHTML = ` `;
38 |
39 | button.addEventListener('click', () => {
40 | t.media.originalNode.webkitShowPlaybackTargetPicker();
41 | });
42 |
43 | const acceptAirPlay = t.media.originalNode.getAttribute('x-webkit-airplay');
44 | if (!acceptAirPlay || acceptAirPlay !== 'allow') {
45 | t.media.originalNode.setAttribute('x-webkit-airplay', 'allow');
46 | }
47 |
48 | t.media.originalNode.addEventListener('webkitcurrentplaybacktargetiswirelesschanged', () => {
49 | const
50 | name = t.media.originalNode.webkitCurrentPlaybackTargetIsWireless ? 'Started' : 'Stopped',
51 | status = t.media.originalNode.webkitCurrentPlaybackTargetIsWireless ? 'active' : '',
52 | icon = button.querySelector('button'),
53 | event = mejs.Utils.createEvent(`airplay${name}`, t.media)
54 | ;
55 | t.media.dispatchEvent(event);
56 |
57 | if (status === 'active') {
58 | mejs.Utils.addClass(icon, 'active');
59 | } else {
60 | mejs.Utils.removeClass(icon, 'active');
61 | }
62 | });
63 |
64 | t.media.originalNode.addEventListener('webkitplaybacktargetavailabilitychanged', (e) => {
65 | if (e.availability === 'available') {
66 | t.addControlElement(button, 'airplay');
67 | }
68 | });
69 | }
70 | });
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/airplay/airplay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/airplay/airplay.png
--------------------------------------------------------------------------------
/src/airplay/airplay.svg:
--------------------------------------------------------------------------------
1 | 7
--------------------------------------------------------------------------------
/src/chromecast/chromecast.css:
--------------------------------------------------------------------------------
1 | .mejs__chromecast-button > button,
2 | .mejs-chromecast-button > button {
3 | --disconnected-color: #fff;
4 | background: none;
5 | display: inline-block;
6 | }
7 | .mejs__chromecast-container,
8 | .mejs-chromecast-container {
9 | background: #000;
10 | color: #fff;
11 | font-size: 10px;
12 | left: 0;
13 | padding: 5px;
14 | position: absolute;
15 | top: 0;
16 | z-index: 1;
17 | }
18 |
19 | .mejs__chromecast-layer > img,
20 | .mejs-chromecast-layer > img {
21 | left: 0;
22 | position: absolute;
23 | top: 0;
24 | z-index: 0;
25 | }
26 |
27 | .mejs__chromecast-icon,
28 | .mejs-chromecast-icon {
29 | background: url('chromecast.svg') no-repeat 0 0;
30 | display: inline-block;
31 | height: 14px;
32 | margin-right: 5px;
33 | width: 17px;
34 | }
--------------------------------------------------------------------------------
/src/chromecast/chromecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/chromecast/chromecast.png
--------------------------------------------------------------------------------
/src/chromecast/chromecast.svg:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/src/context-menu/context-menu.css:
--------------------------------------------------------------------------------
1 | .mejs__contextmenu,
2 | .mejs-contextmenu {
3 | background: #fff;
4 | border: solid 1px #999;
5 | border-radius: 4px;
6 | left: 0;
7 | padding: 10px;
8 | position: absolute;
9 | top: 0;
10 | width: 150px;
11 | z-index: 9999999999; /* make sure it shows on fullscreen */
12 | }
13 |
14 | .mejs__contextmenu-separator,
15 | .mejs-contextmenu-separator {
16 | background: #333;
17 | font-size: 0;
18 | height: 1px;
19 | margin: 5px 6px;
20 | }
21 |
22 | .mejs__contextmenu-item,
23 | .mejs-contextmenu-item {
24 | color: #333;
25 | cursor: pointer;
26 | font-size: 12px;
27 | padding: 4px 6px;
28 | }
29 |
30 | .mejs__contextmenu-item:hover,
31 | .mejs-contextmenu-item:hover {
32 | background: #2c7c91;
33 | color: #fff;
34 | }
35 |
--------------------------------------------------------------------------------
/src/facebook-pixel/facebook-pixel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Facebook Pixel Plugin
3 | *
4 | * This feature enables Facebook Pixel to send certain events, such as play, pause, ended, etc. It requires previous configuration
5 | * on Pixel to send events properly.
6 | * @see https://developers.facebook.com/docs/facebook-pixel
7 | */
8 |
9 | // Feature configuration
10 | Object.assign(mejs.MepDefaults, {
11 | /**
12 | * @type {String}
13 | */
14 | facebookPixelTitle: '',
15 | /**
16 | * @type {String}
17 | */
18 | facebookPixelCategory: 'Videos'
19 | });
20 |
21 | Object.assign(MediaElementPlayer.prototype, {
22 |
23 | /**
24 | * Feature constructor.
25 | *
26 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
27 | * @param {MediaElementPlayer} player
28 | * @param {HTMLElement} controls
29 | * @param {HTMLElement} layers
30 | * @param {HTMLElement} media
31 | */
32 | buildfacebookpixel (player, controls, layers, media) {
33 | player.fbPixelPlay = () => {
34 | if (typeof fbq !== 'undefined') {
35 | fbq('trackCustom', player.options.facebookPixelCategory, {
36 | Event: 'Play',
37 | Title: player.options.facebookPixelTitle === '' ? player.media.currentSrc :
38 | player.options.facebookPixelTitle
39 | });
40 | }
41 | };
42 | player.fbPixelPause = () => {
43 | if (typeof fbq !== 'undefined') {
44 | fbq('trackCustom', player.options.facebookPixelCategory, {
45 | Event: 'Pause',
46 | Title: player.options.facebookPixelTitle === '' ? player.media.currentSrc :
47 | player.options.facebookPixelTitle
48 | });
49 | }
50 | };
51 | player.fbPixelEnded = () => {
52 | if (typeof fbq !== 'undefined') {
53 | fbq('trackCustom', player.options.facebookPixelCategory, {
54 | Event: 'Ended',
55 | Title: player.options.facebookPixelTitle === '' ? player.media.currentSrc :
56 | player.options.facebookPixelTitle
57 | });
58 | }
59 | };
60 |
61 | media.addEventListener('play', player.fbPixelPlay);
62 | media.addEventListener('pause', player.fbPixelPause);
63 | media.addEventListener('ended', player.fbPixelEnded);
64 | },
65 | cleanfacebookpixel (player, controls, layers, media) {
66 | media.removeEventListener('play', player.fbPixelPlay);
67 | media.removeEventListener('pause', player.fbPixelPause);
68 | media.removeEventListener('ended', player.fbPixelEnded);
69 | }
70 | });
71 |
--------------------------------------------------------------------------------
/src/google-analytics/google-analytics.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Google Analytics Plugin
5 | *
6 | * This feature enables GA to send certain events, such as play, pause, ended, etc. It requires previous configuration
7 | * on GA to send events properly.
8 | * @see https://developers.google.com/analytics/devguides/collection/analyticsjs/events
9 | */
10 |
11 |
12 | // Feature configuration
13 | Object.assign(mejs.MepDefaults, {
14 | /**
15 | * @type {String}
16 | */
17 | googleAnalyticsTitle: '',
18 | /**
19 | * @type {String}
20 | */
21 | googleAnalyticsCategory: 'Videos',
22 | /**
23 | * @type {String}
24 | */
25 | googleAnalyticsEventPlay: 'Play',
26 | /**
27 | * @type {String}
28 | */
29 | googleAnalyticsEventPause: 'Pause',
30 | /**
31 | * @type {String}
32 | */
33 | googleAnalyticsEventEnded: 'Ended',
34 | /**
35 | * @type {String}
36 | */
37 | googleAnalyticsEventTime: 'Time'
38 | });
39 |
40 |
41 | Object.assign(MediaElementPlayer.prototype, {
42 |
43 | /**
44 | * Feature constructor.
45 | *
46 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
47 | * @param {MediaElementPlayer} player
48 | * @param {HTMLElement} controls
49 | * @param {HTMLElement} layers
50 | * @param {HTMLElement} media
51 | */
52 | buildgoogleanalytics (player, controls, layers, media) {
53 |
54 | media.addEventListener('play', () => {
55 | if (typeof ga !== 'undefined') {
56 | ga('send', 'event',
57 | player.options.googleAnalyticsCategory,
58 | player.options.googleAnalyticsEventPlay,
59 | (player.options.googleAnalyticsTitle === '') ? player.media.currentSrc : player.options.googleAnalyticsTitle
60 | );
61 | }
62 | }, false);
63 |
64 | media.addEventListener('pause', () => {
65 | if (typeof ga !== 'undefined') {
66 | ga('send', 'event',
67 | player.options.googleAnalyticsCategory,
68 | player.options.googleAnalyticsEventPause,
69 | (player.options.googleAnalyticsTitle === '') ? player.media.currentSrc : player.options.googleAnalyticsTitle
70 | );
71 | }
72 | }, false);
73 |
74 | media.addEventListener('ended', () => {
75 | if (typeof ga !== 'undefined') {
76 | ga('send', 'event',
77 | player.options.googleAnalyticsCategory,
78 | player.options.googleAnalyticsEventEnded,
79 | (player.options.googleAnalyticsTitle === '') ? player.media.currentSrc : player.options.googleAnalyticsTitle
80 | );
81 | }
82 | }, false);
83 | }
84 | });
--------------------------------------------------------------------------------
/src/google-tag-manager/google-tag-manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Google Tag Manager Plugin
3 | *
4 | * This feature enables Google Tag Manager to send certain events, such as play, pause, ended, etc. It requires previous configuration
5 | * on Google Tag Manager configuration to send events properly. For more information, check
6 | * https://support.google.com/tagmanager/answer/6102821?hl=en
7 | *
8 | * @see https://developers.google.com/tag-manager/
9 | */
10 |
11 | // Feature configuration
12 | Object.assign(mejs.MepDefaults, {
13 | /**
14 | * @type {Array}
15 | */
16 | dataLayer: []
17 | });
18 |
19 | Object.assign(MediaElementPlayer.prototype, {
20 |
21 | /**
22 | * Feature constructor.
23 | *
24 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
25 | * @param {MediaElementPlayer} player
26 | * @param {HTMLElement} controls
27 | * @param {HTMLElement} layers
28 | * @param {HTMLElement} media
29 | */
30 | buildgoogletagmanager (player, controls, layers, media) {
31 | player.tagManagerPlay = () => {
32 | if (typeof dataLayer !== 'undefined') {
33 | dataLayer.push({'event': 'clickPlay'});
34 | }
35 | };
36 | player.tagManagerPause = () => {
37 | if (typeof dataLayer !== 'undefined') {
38 | dataLayer.push({'event': 'clickPause'});
39 | }
40 | };
41 | player.tagManagerEnded = () => {
42 | if (typeof dataLayer !== 'undefined') {
43 | dataLayer.push({'event': 'clickEnded'});
44 | }
45 | };
46 |
47 | media.addEventListener('play', player.tagManagerPlay);
48 | media.addEventListener('pause', player.tagManagerPause);
49 | media.addEventListener('ended', player.tagManagerEnded);
50 | },
51 | cleangoogletagmanager (player, controls, layers, media) {
52 | media.removeEventListener('play', player.tagManagerPlay);
53 | media.removeEventListener('pause', player.tagManagerPause);
54 | media.removeEventListener('ended', player.tagManagerEnded);
55 | }
56 | });
57 |
--------------------------------------------------------------------------------
/src/header.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * MediaElement.js
3 | * http://www.mediaelementjs.com/
4 | *
5 | * Wrapper that mimics native HTML5 MediaElement (audio and video)
6 | * using a variety of technologies (pure JavaScript, Flash, iframe)
7 | *
8 | * Copyright 2010-2017, John Dyer (http://j.hn/)
9 | * License: MIT
10 | *
11 | */
--------------------------------------------------------------------------------
/src/jump-forward/jump-forward.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Jump forward button
5 | *
6 | * This feature creates a button to forward media a specific number of seconds.
7 | */
8 |
9 | // Translations (English required)
10 | mejs.i18n.en['mejs.time-jump-forward'] = ['Jump forward 1 second', 'Jump forward %1 seconds'];
11 |
12 | Object.assign(mejs.MepDefaults, {
13 | /**
14 | * @type {Number}
15 | */
16 | jumpForwardInterval: 30,
17 | /**
18 | * @type {?String}
19 | */
20 | jumpForwardText: null,
21 | /**
22 | * The path where the icon sprite is located
23 | * @type {String}
24 | */
25 | iconSpritePathJumpForward: 'mejs-jump-forward.svg',
26 | });
27 |
28 | Object.assign(MediaElementPlayer.prototype, {
29 | /**
30 | * Feature constructor.
31 | *
32 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
33 | * @param {MediaElementPlayer} player
34 | * @param {HTMLElement} controls
35 | * @param {HTMLElement} layers
36 | * @param {HTMLElement} media
37 | */
38 | buildjumpforward (player, controls, layers, media) {
39 |
40 | const
41 | t = this,
42 | defaultTitle = mejs.i18n.t('mejs.time-jump-forward', t.options.jumpForwardInterval),
43 | forwardTitle = mejs.Utils.isString(t.options.jumpForwardText) ? t.options.jumpForwardText.replace('%1', t.options.jumpForwardInterval) : defaultTitle,
44 | button = document.createElement('div')
45 | ;
46 |
47 | button.className = `${t.options.classPrefix}button ${t.options.classPrefix}jump-forward-button`;
48 | button.innerHTML = mejs.Utils.generateControlButton(t.id, forwardTitle, forwardTitle, t.media.options.iconSpritePathJumpForward, ['icon-jump-forward'], t.options.classPrefix);
49 |
50 | t.addControlElement(button, 'jumpforward');
51 |
52 | // add a click toggle event
53 | button.addEventListener('click', function() {
54 | const duration = !isNaN(media.duration) ? media.duration : t.options.jumpForwardInterval;
55 | if (duration) {
56 | const current = media.currentTime === Infinity ? 0 : media.currentTime;
57 | media.setCurrentTime(Math.min(current + t.options.jumpForwardInterval, duration));
58 | }
59 | });
60 | }
61 | });
62 |
--------------------------------------------------------------------------------
/src/jump-forward/jumpforward.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 30
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/loop/loop-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.loop'] = 'Commuta Bucle';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.loop'] = 'Přepnout smyčku';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.loop'] = 'Wiederholung (de-)aktivieren';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.loop'] = 'Alternar Repetición';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.loop'] = 'حلقه تعویض';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.loop'] = 'Répéter';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.loop'] = 'Uključi/isključi ponavljanje';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.loop'] = 'Húzza át a kapcsolót';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.loop'] = 'Passare il ciclo';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.loop'] = 'トグルループ';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.loop'] = '루프 토글';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.loop'] = 'Togol ulangan';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.loop'] = 'Schakellus';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.loop'] = 'Zapętl';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.loop'] = 'Loop alternativo';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.loop'] = 'Comutați buclă';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.loop'] = 'Зациклить воспроизведение';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.loop'] = 'Prepínať slučku';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.loop'] = 'Repetera';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.loop'] = 'Döngü';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.loop'] = 'Повторювати';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.loop'] = '切換循環';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.loop'] = '切换循环';
71 | }
72 |
--------------------------------------------------------------------------------
/src/loop/loop.css:
--------------------------------------------------------------------------------
1 | .mejs__loop-button > button,
2 | .mejs-loop-button > button {
3 | background: url('loop.svg') no-repeat transparent;
4 | }
5 | .mejs__loop-off > button,
6 | .mejs-loop-off > button {
7 | background-position: -20px 1px;
8 | }
9 |
10 | .mejs__loop-on > button,
11 | .mejs-loop-on > button {
12 | background-position: 0 1px;
13 | }
14 |
--------------------------------------------------------------------------------
/src/loop/loop.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Loop button
5 | *
6 | * This feature creates a loop button in the control bar to toggle its behavior. It will restart media once finished
7 | * if activated
8 | */
9 |
10 | // Translations (English required)
11 | mejs.i18n.en['mejs.loop'] = 'Toggle Loop';
12 |
13 | // Feature configuration
14 | Object.assign(mejs.MepDefaults, {
15 | /**
16 | * @type {?String}
17 | */
18 | loopText: null
19 | });
20 |
21 | Object.assign(MediaElementPlayer.prototype, {
22 | /**
23 | * Feature constructor.
24 | *
25 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
26 | * @param {MediaElementPlayer} player
27 | */
28 | buildloop (player) {
29 | const
30 | t = this,
31 | loopTitle = mejs.Utils.isString(t.options.loopText) ? t.options.loopText : mejs.i18n.t('mejs.loop'),
32 | loop = document.createElement('div')
33 | ;
34 |
35 | loop.className = `${t.options.classPrefix}button ${t.options.classPrefix}loop-button ${((player.options.loop) ? `${t.options.classPrefix}loop-on` : `${t.options.classPrefix}loop-off`)}`;
36 | loop.innerHTML = ` `;
37 |
38 | t.addControlElement(loop, 'loop');
39 |
40 | // add a click toggle event
41 | loop.addEventListener('click', () => {
42 | player.options.loop = !player.options.loop;
43 | if (player.options.loop) {
44 | mejs.Utils.removeClass(loop, `${t.options.classPrefix}loop-off`);
45 | mejs.Utils.addClass(loop, `${t.options.classPrefix}loop-on`);
46 | } else {
47 | mejs.Utils.removeClass(loop, `${t.options.classPrefix}loop-on`);
48 | mejs.Utils.addClass(loop, `${t.options.classPrefix}loop-off`);
49 | }
50 | });
51 | }
52 | });
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/loop/loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/loop/loop.png
--------------------------------------------------------------------------------
/src/loop/loop.svg:
--------------------------------------------------------------------------------
1 | 4
--------------------------------------------------------------------------------
/src/picture-in-picture/picture-in-picture-i18n.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | if(mejs.i18n.es !== undefined) {
4 | mejs.i18n.es['mejs.picture-in-pictureText'] = 'Picture in picture';
5 | }
6 | if (mejs.i18n.de !== undefined) {
7 | mejs.i18n.de['mejs.picture-in-pictureText'] = 'Bild in Bild';
8 | }
9 | if(mejs.i18n.fr !== undefined) {
10 | mejs.i18n.fr['mejs.picture-in-pictureText'] = 'Image dans l’image';
11 | }
12 | if(mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.picture-in-pictureText'] = 'Imagen dentro de imagen';
14 | }
15 |
16 |
17 | // TODO Add more languages for the title attribute
18 |
--------------------------------------------------------------------------------
/src/picture-in-picture/picture-in-picture.css:
--------------------------------------------------------------------------------
1 | #picture-in-picture-button {
2 | background-color: transparent;
3 | background-image: url(picture-in-picture.svg);
4 | background-position:center;
5 | background-repeat: no-repeat;
6 | background-size: auto;
7 | border: none;
8 | color: #fff;
9 | width: 30px;
10 | }
11 |
--------------------------------------------------------------------------------
/src/picture-in-picture/picture-in-picture.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Picture in picture
5 | *
6 | *
7 | * This feature is currently supported by safari 11 and chrome (70)
8 | *
9 | * Univream - 2018
10 | */
11 |
12 |
13 | mejs.i18n.en['mejs.picture-in-pictureText'] = "Picture in Picture";
14 |
15 | // Feature configuration
16 | Object.assign(mejs.MepDefaults, {
17 | /**
18 | * @type {?String} PiPTitle - Hover title of pip-button
19 | */
20 | PiPTitle: null
21 | });
22 |
23 |
24 | Object.assign(MediaElementPlayer.prototype, {
25 |
26 | /**
27 | * Feature constructor.
28 | */
29 | buildpictureInPicture () {
30 |
31 | const
32 | t = this,
33 | buttonWrapper = document.createElement('div'),
34 | button = document.createElement('button'),
35 | video = t.node;
36 |
37 | button.setAttribute('type', 'button');
38 | button.setAttribute('id', 'picture-in-picture-button');
39 | button.setAttribute('title', t.options.PiPTitle == null ? mejs.i18n.t('mejs.picture-in-pictureText') : t.options.PiPTitle);
40 | buttonWrapper.className = `${t.options.classPrefix}button ${t.options.classPrefix}picture-in-picture-button`;
41 | buttonWrapper.appendChild(button);
42 |
43 | if(video instanceof HTMLVideoElement) {
44 | // This is currently not a W3C standard (25-10-2018)
45 | // https://wicg.github.io/picture-in-picture/
46 | if(document.pictureInPictureEnabled && !video.disablePictureInPicture) {
47 | button.addEventListener('click', () => {
48 | if(!document.pictureInPictureElement) {
49 | video.requestPictureInPicture()
50 | .catch(() => {
51 | // Handle error
52 | });
53 | }
54 | else {
55 | document.exitPictureInPicture()
56 | .catch(() => {
57 | // Handle error
58 | });
59 | }
60 | });
61 | }
62 | // Safari implmentation
63 | else if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
64 | // For more info https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls?language=javascript
65 | // Toggle PiP when the user clicks the button.
66 | button.addEventListener("click", function() {
67 | video.webkitSetPresentationMode(video.webkitPresentationMode === "picture-in-picture" ? "inline" : "picture-in-picture");
68 | });
69 | }
70 | else {
71 | return;
72 | }
73 | }
74 |
75 | t.addControlElement(buttonWrapper, 'pictureInPicture');
76 | }
77 | });
78 |
--------------------------------------------------------------------------------
/src/picture-in-picture/picture-in-picture.svg:
--------------------------------------------------------------------------------
1 |
2 |
13 |
15 |
19 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/postroll/postroll-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.close'] = 'Tancar';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.close'] = 'Zavřít';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.close'] = 'Schließen';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.close'] = 'Cerrar';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.close'] = 'نزدیک';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.close'] = 'Fermer';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.close'] = 'Zatvori';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.close'] = 'Bezárás';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.close'] = 'Chiudere';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.close'] = '閉じる';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.close'] = '종료';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.close'] = 'Tutup';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.close'] = 'Sluiten';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.close'] = 'Zamknij';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.close'] = 'Fechar';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.close'] = 'Închide';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.close'] = 'Закрыть';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.close'] = 'Zavrieť';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.close'] = 'Stäng';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.close'] = 'Kapat';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.close'] = 'Закрити';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.close'] = '關閉';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.close'] = '关闭';
71 | }
72 |
--------------------------------------------------------------------------------
/src/postroll/postroll.css:
--------------------------------------------------------------------------------
1 | .mejs__postroll-layer,
2 | .mejs-postroll-layer {
3 | background: rgba(50, 50, 50, 0.7);
4 | bottom: 0;
5 | height: 100%;
6 | left: 0;
7 | overflow: hidden;
8 | position: absolute;
9 | width: 100%;
10 | z-index: 1000;
11 | }
12 |
13 | .mejs__postroll-layer-content,
14 | .mejs-postroll-layer-content {
15 | height: 100%;
16 | width: 100%;
17 | }
18 | .mejs__postroll-close,
19 | .mejs-postroll-close {
20 | background: rgba(50, 50, 50, 0.7);
21 | color: #fff;
22 | cursor: pointer;
23 | padding: 4px;
24 | position: absolute;
25 | right: 0;
26 | top: 0;
27 | z-index: 100;
28 | }
29 |
--------------------------------------------------------------------------------
/src/postroll/postroll.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Postroll plugin
5 | *
6 | * This feature allows the injection of any HTML content in an independent layer once the media finished.
7 | * To activate it, one of the nodes contained in the `` tag must be
8 | * ` `
9 | */
10 |
11 | // Translations (English required)
12 | mejs.i18n.en['mejs.close'] = 'Close';
13 |
14 | // Feature configuration
15 | Object.assign(mejs.MepDefaults, {
16 | /**
17 | * @type {?String}
18 | */
19 | postrollCloseText: null
20 | });
21 |
22 | Object.assign(MediaElementPlayer.prototype, {
23 |
24 | /**
25 | * Feature constructor.
26 | *
27 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
28 | * @param {MediaElementPlayer} player
29 | * @param {HTMLElement} controls
30 | * @param {HTMLElement} layers
31 | */
32 | buildpostroll (player, controls, layers) {
33 | const
34 | t = this,
35 | postrollTitle = mejs.Utils.isString(t.options.postrollCloseText) ? t.options.postrollCloseText : mejs.i18n.t('mejs.close'),
36 | postrollLink = t.container.querySelector('link[rel="postroll"]')
37 | ;
38 |
39 | if (postrollLink) {
40 | player.postroll = document.createElement('div');
41 | player.postroll.className = `${t.options.classPrefix}postroll-layer ${t.options.classPrefix}layer`;
42 | player.postroll.innerHTML = `${postrollTitle} ` +
43 | `
`;
44 | player.postroll.style.display = 'none';
45 |
46 | layers.insertBefore(player.postroll, layers.firstChild);
47 |
48 | player.postroll.querySelector(`.${t.options.classPrefix}postroll-close`).addEventListener('click', function (e) {
49 | this.parentNode.style.display = 'none';
50 | e.preventDefault();
51 | e.stopPropagation();
52 | });
53 |
54 | t.media.addEventListener('ended', () => {
55 | mejs.Utils.ajax(postrollLink.getAttribute('href'), 'html', (data) => {
56 | layers.querySelector(`.${t.options.classPrefix}postroll-layer-content`).innerHTML = data;
57 | });
58 | player.postroll.style.display = 'block';
59 | }, false);
60 |
61 | t.media.addEventListener('seeked', () => {
62 | player.postroll.style.display = 'none';
63 | }, false);
64 |
65 | t.media.addEventListener('playing', () => {
66 | player.postroll.style.display = 'none';
67 | }, false);
68 | }
69 | }
70 | });
--------------------------------------------------------------------------------
/src/quality/quality-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.quality-chooser']= 'Selector de qualitat';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.quality-chooser']= 'Kvalitní výběr';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.quality-chooser']= 'Qualitätswähler';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.quality-chooser']= 'Selector de calidad';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.quality-chooser']= 'انتخاب کننده کیفیت';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.quality-chooser']= 'Sélecteur de qualité';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.quality-chooser']= 'Kvalitetni birač';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.quality-chooser']= 'Minőségi választó';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.quality-chooser']= 'Qualità scelto';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.quality-chooser']= '品質チューザー';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.quality-chooser']= '품질 선택자';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.quality-chooser']= 'Pilih kualiti';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.quality-chooser']= 'Kwaliteit kiezer';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.quality-chooser']= 'Chooser jakości';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.quality-chooser']= 'Escolha de qualidade';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.quality-chooser']= 'Alegere de calitate';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.quality-chooser']= 'Выбор качества';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.quality-chooser']= 'Kvalitný výber';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.quality-chooser']= 'Kvalitetsvalare';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.quality-chooser']= 'Kalite';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.quality-chooser']= 'Вибір якості';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.quality-chooser']= '質量選擇';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.quality-chooser']= '质量选择';
71 | }
72 |
--------------------------------------------------------------------------------
/src/quality/quality.css:
--------------------------------------------------------------------------------
1 | .mejs__qualities-selector.mejs__offscreen {
2 | display: none;
3 | }
4 |
5 | .mejs__qualities-button,
6 | .mejs-qualities-button {
7 | position: relative;
8 | width: auto;
9 | }
10 |
11 | .mejs__qualities-button > button,
12 | .mejs-qualities-button > button {
13 | background: transparent;
14 | color: #fff;
15 | font-size: 0.6875rem;
16 | font-weight: 700;
17 | position: static;
18 | width: auto;
19 | }
20 |
21 | .mejs__qualities-selector,
22 | .mejs-qualities-selector {
23 | background: rgba(50, 50, 50, 0.7);
24 | border: 0.063rem solid transparent;
25 | border-radius: 0;
26 | height: 6.25rem;
27 | left: -0.625rem;
28 | overflow: hidden;
29 | padding: 0;
30 | position: absolute;
31 | top: -6.25rem;
32 | width: 3.75rem;
33 | }
34 |
35 | .mejs__qualities-selector ul,
36 | .mejs-qualities-selector ul {
37 | display: block;
38 | list-style-type: none !important;
39 | margin: 0;
40 | overflow: hidden;
41 | padding: 0;
42 | }
43 |
44 | .mejs__qualities-selector li,
45 | .mejs-qualities-selector li {
46 | border: 0.06rem solid transparent;
47 | color: #fff;
48 | cursor: pointer;
49 | display: block;
50 | list-style-type: none!important;
51 | overflow: hidden;
52 | padding: 0 0.625rem;
53 | }
54 |
55 | .mejs__qualities-selector li:hover,
56 | .mejs-qualities-selector li:hover {
57 | background-color: rgba(255, 255, 255, 0.2);
58 | cursor: pointer;
59 | }
60 |
61 | .mejs__qualities-selector li:focus-within,
62 | .mejs-qualities-selector li:focus-within {
63 | border-color: #fff;
64 | }
65 |
66 | .mejs__qualities-selector input,
67 | .mejs-qualities-selector input {
68 | clear: both;
69 | float: left;
70 | left: -62.5rem;
71 | margin: 0.188rem 0.188rem 0 0.313rem;
72 | position: absolute;
73 | }
74 |
75 | .mejs__qualities-selector label,
76 | .mejs-qualities-selector label {
77 | cursor: pointer;
78 | float: left;
79 | font-size: 0.625rem;
80 | padding: 0.375rem 0;
81 | width: 3.438rem;
82 | }
83 |
84 | .mejs__qualities-selected,
85 | .mejs-qualities-selected {
86 | color: rgba(33, 248, 248, 1);
87 | }
88 |
--------------------------------------------------------------------------------
/src/skip-back/skip-back.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Skip back button
5 | *
6 | * This feature creates a button to rewind media a specific number of seconds.
7 | */
8 |
9 | // Translations (English required)
10 | mejs.i18n.en['mejs.time-skip-back'] = ['Skip back 1 second', 'Skip back %1 seconds'];
11 |
12 | // Feature configuration
13 | Object.assign(mejs.MepDefaults, {
14 | /**
15 | * @type {Number}
16 | */
17 | skipBackInterval: 30,
18 | /**
19 | * @type {?String}
20 | */
21 | skipBackText: null,
22 | /**
23 | * The path where the icon sprite is located
24 | * @type {String}
25 | */
26 | iconSpritePathSkipBack: 'mejs-skip-back.svg',
27 | });
28 |
29 | Object.assign(MediaElementPlayer.prototype, {
30 |
31 | /**
32 | * Feature constructor.
33 | *
34 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
35 | * @param {MediaElementPlayer} player
36 | * @param {HTMLElement} controls
37 | * @param {HTMLElement} layers
38 | * @param {HTMLElement} media
39 | */
40 | buildskipback (player, controls, layers, media) {
41 | const
42 | t = this,
43 | defaultTitle = mejs.i18n.t('mejs.time-skip-back', t.options.skipBackInterval),
44 | skipTitle = mejs.Utils.isString(t.options.skipBackText) ? t.options.skipBackText.replace('%1', t.options.skipBackInterval) : defaultTitle,
45 | button = document.createElement('div')
46 | ;
47 |
48 | button.className = `${t.options.classPrefix}button ${t.options.classPrefix}skip-back-button`;
49 | button.innerHTML = mejs.Utils.generateControlButton(t.id, skipTitle, skipTitle, t.media.options.iconSpritePathSkipBack, ['icon-skip-back'], t.options.classPrefix);
50 |
51 | t.addControlElement(button, 'skipback');
52 |
53 | // add a click toggle event
54 | button.addEventListener('click', function() {
55 | const duration = !isNaN(media.duration) ? media.duration : t.options.skipBackInterval;
56 | if (duration) {
57 | const current = media.currentTime === Infinity ? 0 : media.currentTime;
58 | media.setCurrentTime(Math.max(current - t.options.skipBackInterval, 0));
59 | }
60 | });
61 | }
62 | });
63 |
--------------------------------------------------------------------------------
/src/skip-back/skipback.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 30
8 |
9 |
--------------------------------------------------------------------------------
/src/snapshot/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 |
5 | /* load package */
6 |
7 | pkg: grunt.file.readJSON('package.json'),
8 |
9 | /**
10 | * Add tasks
11 | */
12 |
13 | watch: {
14 | js:{
15 | files: [
16 | 'snapshot.js'
17 | ],
18 | tasks:['uglify']
19 | },
20 |
21 | css: {
22 | files: [
23 | 'snapshot.css'
24 | ],
25 | tasks:['cssmin']
26 | }
27 | },
28 |
29 | /*
30 | * compress and mangle the input file using the default options.
31 | */
32 | uglify: {
33 |
34 | js: {
35 | files: {
36 | 'snapshot.min.js': ['snapshot.js']
37 | }
38 | }
39 |
40 | },
41 |
42 |
43 | cssmin: {
44 |
45 | css: {
46 | src: 'snapshot.css',
47 | dest: 'snapshot.min.css'
48 | }
49 |
50 | }
51 |
52 | });
53 |
54 |
55 | // Load modules
56 | grunt.loadNpmTasks('grunt-contrib-watch');
57 | grunt.loadNpmTasks('grunt-contrib-uglify-es');
58 | grunt.loadNpmTasks('grunt-css');
59 |
60 |
61 | // Register the default tasks.
62 | grunt.registerTask('default', ['watch']);
63 |
64 | };
65 |
--------------------------------------------------------------------------------
/src/snapshot/README.md:
--------------------------------------------------------------------------------
1 | # Mediaelement Snapshot
2 |
3 | * Author: Yassine Qoraiche
4 | * Website: https://codecsocean.com/
5 | * License: MIT
6 |
7 | ## Overview
8 |
9 | Mediaelement Snapshot plugin creates a button in the player controls allows to take video snapshots with different image types (jpeg, png).
10 |
11 | ## Installation
12 |
13 | Download plugin files and place the js files after the main [Mediaelement](https://github.com/mediaelement/mediaelement/) player js `mediaelement-and-player.min.js` file:
14 |
15 | ```HTML
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ```
24 | Place plugin main CSS style after the main player stylesheet
25 |
26 | ```HTML
27 |
28 |
29 |
30 |
31 |
32 |
33 | ```
34 |
35 | Add plugin keyword to the features list
36 |
37 | ```Javascript
38 | features: [..., 'snapshot']
39 | ```
40 |
41 | That's it !.
42 |
43 | For more details about [How to Install mediaelement plugin](https://github.com/mediaelement/mediaelement-plugins#installation).
44 |
45 | ## Usage
46 |
47 | Initialize Snapshot plugin
48 |
49 | ```Javascript
50 |
51 | var player = new MediaElementPlayer(document.querySelector('video'), {
52 |
53 | features:['play', 'playpause', volume', 'progress', 'snapshot', fullscreen'],
54 |
55 | snapType:'jpeg',
56 | snapQuality: 0.5, //half quality
57 | snapShot: true,
58 |
59 | snapSuccess: function(snap){
60 | console.log(snap.url); //return snap object
61 | },
62 |
63 | snapError: function(){
64 | console.log('you can not take snapshot while the player loading !');
65 | }
66 |
67 | });
68 |
69 | ```
70 |
71 | ## API
72 |
73 | | Parameter | Type | Default | Description |
74 | | ----------- | -------------- | --------| -----------
75 | | snapShot | boolean | `true` | Either to save snapshot image locally (`true`) or not (`false`)
76 | | snapType | string | `png` | Type of image `png`or `jpeg`
77 | | snapWidth | number | Default video width | Snapshot image width
78 | | snapHeight | number | Default video height | Snapshot image height
79 | | snapQuality | number or float | `1` | Snapshot image quality between `0` and `1`
80 | | snapSuccess | function() | `null` | success callback => (snapshot) accepts one parameter contains snapshot object
81 | | snapError | function() | `null` | error callback() => () accepts no parameters
82 |
83 | ## Support
84 |
85 | Having trouble with this plugin? [create an issue](https://github.com/Codecsocean/mediaelement-snapshot/issues) describing the problem that you have encountered.
86 |
87 |
--------------------------------------------------------------------------------
/src/snapshot/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/src/snapshot/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "snapshot",
3 | "version": "1.0.0",
4 | "description": "Mediaelements snapshot plugin allows to get and save video snapshots locally ",
5 | "main": "snapshot.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "mediaelements-plugins",
11 | "video",
12 | "snapshot",
13 | "video",
14 | "screenshot",
15 | "mediaelementsjs",
16 | "snapshot"
17 | ],
18 | "author": "Qoraiche",
19 | "license": "ISC",
20 | "devDependencies": {
21 | "grunt": "^1.0.2",
22 | "grunt-contrib-uglify": "^3.3.0",
23 | "grunt-contrib-uglify-es": "git://github.com/gruntjs/grunt-contrib-uglify.git#harmony",
24 | "grunt-contrib-watch": "^1.0.1",
25 | "grunt-css": "^0.5.4"
26 | },
27 | "dependencies": {}
28 | }
29 |
--------------------------------------------------------------------------------
/src/snapshot/snapshot-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.snapshot'] = ['Retornar 1 segon', 'Retornar %1 segons'];
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.snapshot'] = ['Přeskočte zpět o 1 sekundu', 'Přeskočte zpět %1 vteřiny', 'Přeskočte zpět %1 sekund'];
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.snapshot'] = ['1 Sekunde zurückspulen', '%1 Sekunden zurückspulen'];
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.snapshot'] = ['Rebobinar 1 segundo', 'Rebobinar %1 segundos'];
14 | }
15 | if (mejs.i18n.fr !== undefined) {
16 | mejs.i18n.fr['mejs.snapshot'] = ['Reculer de %1 seconde', 'Reculer de %1 secondes'];
17 | }
18 | if (mejs.i18n.fa !== undefined) {
19 | mejs.i18n.fa['mejs.snapshot'] = '%1 ثانیه به عقب برگردید';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.snapshot'] = ['Skoči natrag 1 sekundu', 'Skoči natrag %1 sekunde', 'Skoči natrag %1 sekundi'];
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.snapshot'] = ['Menj vissza 1 másodpercig', 'Ugrás vissza %1 másodperccel'];
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.snapshot'] = ['Riavvolgere 1 secondo', 'Riavvolgere %1 secondi'];
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.snapshot'] = '%1秒スキップバックする';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.snapshot'] = '%1초 를 뒤로 건너뛰세요';
35 | }
36 | if (mejs.i18n.nl !== undefined) {
37 | mejs.i18n.nl['mejs.snapshot'] = ['Sla 1 seconde terug', 'Sla %1 seconden terug'];
38 | }
39 | if (mejs.i18n.pl !== undefined) {
40 | mejs.i18n.pl['mejs.snapshot'] = ['Cofnij o 1 sekundę', 'Cofnij o %1 sekundy', 'Cofnij o %1 sekund'];
41 | }
42 | if (mejs.i18n.pt !== undefined) {
43 | mejs.i18n.pt['mejs.snapshot'] = ['Retroceder %1 segundo', 'Retroceder %1 segundos'];
44 | }
45 | if (mejs.i18n.ro !== undefined) {
46 | mejs.i18n.ro['mejs.snapshot'] = ['Treceți înapoi 1 secundă', 'Treceți înapoi în %1 secunde'];
47 | }
48 | if (mejs.i18n.ru !== undefined) {
49 | mejs.i18n.ru['mejs.snapshot'] = ['Перейти назад на %1 секунду', 'Перейти назад на %1 секунды', 'Перейти назад на %1 секунд'];
50 | }
51 | if (mejs.i18n.sk !== undefined) {
52 | mejs.i18n.sk['mejs.snapshot'] = ['Preskočte späť 1 sekundu', 'Preskočte %1 sekundy', 'Preskočte späť %1 sekúnd'];
53 | }
54 | if (mejs.i18n.sv !== undefined) {
55 | mejs.i18n.sv['mejs.snapshot'] = ['Hoppa tillbaka 1 sekund', 'Hoppa tillbaka %1 sekunder'];
56 | }
57 | if (mejs.i18n.tr !== undefined) {
58 | mejs.i18n.tr['mejs.snapshot'] = ['1 saniye geri atla', '%1 saniye geri atla'];
59 | }
60 | if (mejs.i18n.uk !== undefined) {
61 | mejs.i18n.uk['mejs.snapshot'] = ['Перейти назад на %1 секунду', 'Перейти назад на %1 секунди', 'Перейти назад на %1 секунд'];
62 | }
63 | if (mejs.i18n.zh !== undefined) {
64 | mejs.i18n.zh['mejs.snapshot'] = '跳躍式迴繞%1秒';
65 | }
66 | if (mejs.i18n['zh-CN'] !== undefined) {
67 | mejs.i18n['zh-CN']['mejs.snapshot'] = '后退%1秒';
68 | }
69 |
--------------------------------------------------------------------------------
/src/snapshot/snapshot.css:
--------------------------------------------------------------------------------
1 | .mejs__snapshot-button > button,
2 | .mejs-snapshot-button > button {
3 | background: url('snapshot.png') no-repeat 0 -1px;
4 | background-size: contain;
5 | color: #fff;
6 | font-size: 8px;
7 | line-height: normal;
8 | position: relative;
9 | }
10 |
--------------------------------------------------------------------------------
/src/snapshot/snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/snapshot/snapshot.png
--------------------------------------------------------------------------------
/src/source-chooser/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/source-chooser/settings.png
--------------------------------------------------------------------------------
/src/source-chooser/settings.svg:
--------------------------------------------------------------------------------
1 | 3
--------------------------------------------------------------------------------
/src/source-chooser/source-chooser-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.source-chooser']= 'Selector de font';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.source-chooser']= 'Zdrojový výběr';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.source-chooser']= 'Quellenauswahl';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.source-chooser']= 'Selector de media';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.source-chooser']= 'انتخاب کننده منبع';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.source-chooser']= 'Sélecteur de média';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.source-chooser']= 'Obabir izvora';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.source-chooser']= 'Forrásválasztó';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.source-chooser']= 'Selezionatore di origine';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.source-chooser']= 'ソースセレクタ';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.source-chooser']= '소스 선택기';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.source-chooser']= 'Pilih sumber';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.source-chooser']= 'Bronkeuze';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.source-chooser']= 'Wybór źródła';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.source-chooser']= 'Escolhedor de fontes';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.source-chooser']= 'Sursă de selecție';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.source-chooser']= 'Переключатель источника';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.source-chooser']= 'Zdroj výberu';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.source-chooser']= 'Välj källa';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.source-chooser']= 'Kaynak Seçici';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.source-chooser']= 'Вибір джерела';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.source-chooser']= '源選擇器';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.source-chooser']= '源选择器';
71 | }
72 |
--------------------------------------------------------------------------------
/src/source-chooser/source-chooser.css:
--------------------------------------------------------------------------------
1 | .mejs__sourcechooser-button,
2 | .mejs-sourcechooser-button {
3 | position: relative;
4 | }
5 |
6 | .mejs__sourcechooser-button > button,
7 | .mejs-sourcechooser-button > button {
8 | background: url('settings.svg') transparent no-repeat;
9 | background-position: 0 1px;
10 | }
11 |
12 | .mejs__sourcechooser-button .mejs__sourcechooser-selector,
13 | .mejs-sourcechooser-button .mejs-sourcechooser-selector {
14 | background: rgba(50, 50, 50, 0.7);
15 | border: solid 1px transparent;
16 | border-radius: 0;
17 | bottom: 40px;
18 | height: 100px;
19 | overflow: hidden;
20 | padding: 0;
21 | position: absolute;
22 | right: -10px;
23 | width: 130px;
24 | }
25 |
26 | .mejs__sourcechooser-selector ul,
27 | .mejs-sourcechooser-selector ul {
28 | display: block;
29 | list-style-type: none !important;
30 | margin: 0;
31 | overflow: hidden;
32 | padding: 0;
33 | }
34 |
35 | .mejs__sourcechooser-selector li,
36 | .mejs-sourcechooser-selector li {
37 | color: #fff;
38 | display: block;
39 | list-style-type: none !important;
40 | margin: 0;
41 | overflow: hidden;
42 | padding: 5px 0;
43 | }
44 | .mejs__sourcechooser-selector li:hover,
45 | .mejs-sourcechooser-selector li:hover {
46 | background-color: rgba(255, 255, 255, 0.2);
47 | cursor: pointer;
48 | }
49 |
50 | .mejs__sourcechooser-selector input,
51 | .mejs-sourcechooser-selector input {
52 | clear: both;
53 | float: left;
54 | margin: 3px 3px 0 0;
55 | }
56 |
57 | .mejs__sourcechooser-selector label,
58 | .mejs-sourcechooser-selector label {
59 | display: inline-block;
60 | float: left;
61 | font-size: 12px;
62 | line-height: 15px;
63 | padding: 4px 0 0;
64 | width: 100px;
65 | }
66 |
--------------------------------------------------------------------------------
/src/speed/speed-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.speed-rate'] = 'Velocitat';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.speed-rate'] = 'Rychlost';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.speed-rate'] = 'Geschwindigkeitsrate';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.speed-rate'] = 'Velocidad';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.speed-rate'] = 'نرخ سرعت';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.speed-rate'] = 'Vitesse';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.speed-rate'] = 'Brzina reprodukcije';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.speed-rate'] = 'Sebesség';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.speed-rate'] = 'Velocità';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.speed-rate'] = '高速';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.speed-rate'] = '속도 속도';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.speed-rate'] = 'Kelajuan';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.speed-rate'] = 'Snelheidsgraad';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.speed-rate'] = 'Prędkość';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.speed-rate'] = 'Taxa de velocidade';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.speed-rate'] = 'Viteză de viteză';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.speed-rate'] = 'Скорость воспроизведения';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.speed-rate'] = 'Rýchlosť';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.speed-rate'] = 'Hastighet';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.speed-rate'] = 'Hız oranı';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.speed-rate'] = 'Швидкість відтворення';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.speed-rate'] = '速度';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.speed-rate'] = '速度';
71 | }
72 |
--------------------------------------------------------------------------------
/src/speed/speed.css:
--------------------------------------------------------------------------------
1 | .mejs__speed-button,
2 | .mejs-speed-button {
3 | position: relative;
4 | }
5 |
6 | .mejs__speed-button > button,
7 | .mejs-speed-button > button {
8 | background: transparent;
9 | color: #fff;
10 | font-size: 11px;
11 | line-height: normal;
12 | margin: 11px 0 0;
13 | width: 36px;
14 | }
15 |
16 | .mejs__speed-selector,
17 | .mejs-speed-selector {
18 | background: rgba(50, 50, 50, 0.7);
19 | border: solid 1px transparent;
20 | border-radius: 0;
21 | height: 150px;
22 | left: -10px;
23 | overflow: hidden;
24 | padding: 0;
25 | position: absolute;
26 | top: -100px;
27 | visibility: hidden;
28 | width: 60px;
29 | }
30 |
31 | .mejs__speed-selector,
32 | .mejs-speed-selector {
33 | visibility: visible;
34 | }
35 |
36 | .mejs__speed-selector-list,
37 | .mejs-speed-selector-list {
38 | display: block;
39 | list-style-type: none !important;
40 | margin: 0;
41 | overflow: hidden;
42 | padding: 0;
43 | }
44 |
45 | .mejs__speed-selector-list-item,
46 | .mejs-speed-selector-list-item {
47 | color: #fff;
48 | display: block;
49 | list-style-type: none !important;
50 | margin: 0 0 6px;
51 | overflow: hidden;
52 | padding: 0 10px;
53 | }
54 |
55 | .mejs__speed-selector-list-item:hover,
56 | .mejs-speed-selector-list-item:hover {
57 | background-color: rgb(200, 200, 200) !important;
58 | background-color: rgba(255, 255, 255, 0.4) !important;
59 | }
60 |
61 | .mejs__speed-selector-input,
62 | .mejs-speed-selector-input {
63 | clear: both;
64 | float: left;
65 | left: -1000px;
66 | margin: 3px 3px 0 5px;
67 | position: absolute;
68 | }
69 |
70 | .mejs__speed-selector-label,
71 | .mejs-speed-selector-label {
72 | color: white;
73 | cursor: pointer;
74 | float: left;
75 | font-size: 11px;
76 | line-height: 15px;
77 | margin-left: 5px;
78 | padding: 4px 0 0;
79 | width: 60px;
80 | }
81 |
82 | .mejs__speed-selected,
83 | .mejs-speed-selected {
84 | color: rgba(33, 248, 248, 1);
85 | }
86 |
87 | .mejs__speed-selector,
88 | .mejs-speed-selector {
89 | visibility: hidden;
90 | }
91 | .mejs__speed-button:hover .mejs__speed-selector,
92 | .mejs-speed-button:hover .mejs-speed-selector {
93 | visibility: visible;
94 | }
95 |
--------------------------------------------------------------------------------
/src/stop/stop-i18n.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (mejs.i18n.ca !== undefined) {
4 | mejs.i18n.ca['mejs.stop'] = 'Aturar';
5 | }
6 | if (mejs.i18n.cs !== undefined) {
7 | mejs.i18n.cs['mejs.stop'] = 'Stop';
8 | }
9 | if (mejs.i18n.de !== undefined) {
10 | mejs.i18n.de['mejs.stop'] = 'Stop';
11 | }
12 | if (mejs.i18n.es !== undefined) {
13 | mejs.i18n.es['mejs.stop'] = 'Parar';
14 | }
15 | if (mejs.i18n.fa !== undefined) {
16 | mejs.i18n.fa['mejs.stop'] = 'متوقف کردن';
17 | }
18 | if (mejs.i18n.fr !== undefined) {
19 | mejs.i18n.fr['mejs.stop'] = 'Stop';
20 | }
21 | if (mejs.i18n.hr !== undefined) {
22 | mejs.i18n.hr['mejs.stop'] = 'Zaustavi';
23 | }
24 | if (mejs.i18n.hu !== undefined) {
25 | mejs.i18n.hu['mejs.stop'] = 'Állj meg';
26 | }
27 | if (mejs.i18n.it !== undefined) {
28 | mejs.i18n.it['mejs.stop'] = 'Stop';
29 | }
30 | if (mejs.i18n.ja !== undefined) {
31 | mejs.i18n.ja['mejs.stop'] = '止';
32 | }
33 | if (mejs.i18n.ko !== undefined) {
34 | mejs.i18n.ko['mejs.stop'] = '중지';
35 | }
36 | if (mejs.i18n.ms !== undefined) {
37 | mejs.i18n.ms['mejs.stop'] = 'Berhenti';
38 | }
39 | if (mejs.i18n.nl !== undefined) {
40 | mejs.i18n.nl['mejs.stop'] = 'Hou op';
41 | }
42 | if (mejs.i18n.pl !== undefined) {
43 | mejs.i18n.pl['mejs.stop'] = 'Zatrzymaj';
44 | }
45 | if (mejs.i18n.pt !== undefined) {
46 | mejs.i18n.pt['mejs.stop'] = 'Pare';
47 | }
48 | if (mejs.i18n.ro !== undefined) {
49 | mejs.i18n.ro['mejs.stop'] = 'Stop';
50 | }
51 | if (mejs.i18n.ru !== undefined) {
52 | mejs.i18n.ru['mejs.stop'] = 'Остановить';
53 | }
54 | if (mejs.i18n.sk !== undefined) {
55 | mejs.i18n.sk['mejs.stop'] = 'Prestať';
56 | }
57 | if (mejs.i18n.sv !== undefined) {
58 | mejs.i18n.sv['mejs.stop'] = 'Stoppa';
59 | }
60 | if (mejs.i18n.tr !== undefined) {
61 | mejs.i18n.tr['mejs.stop'] = 'Durdur';
62 | }
63 | if (mejs.i18n.uk !== undefined) {
64 | mejs.i18n.uk['mejs.stop'] = 'Зупинити';
65 | }
66 | if (mejs.i18n.zh !== undefined) {
67 | mejs.i18n.zh['mejs.stop'] = '停止';
68 | }
69 | if (mejs.i18n['zh-CN'] !== undefined) {
70 | mejs.i18n['zh-CN']['mejs.stop'] = '停止';
71 | }
72 |
--------------------------------------------------------------------------------
/src/stop/stop.css:
--------------------------------------------------------------------------------
1 | .mejs__stop > button,
2 | .mejs-stop > button {
3 | background: url('stop.svg') 0 2px no-repeat;
4 | }
5 |
--------------------------------------------------------------------------------
/src/stop/stop.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Stop button
5 | *
6 | * This feature enables the displaying of a Stop button in the control bar, which basically pauses the media and rewinds
7 | * it to the initial position.
8 | */
9 |
10 | // Translations (English required)
11 | mejs.i18n.en['mejs.stop'] = 'Stop';
12 |
13 | // Feature configuration
14 | Object.assign(mejs.MepDefaults, {
15 | /**
16 | * @type {?String}
17 | */
18 | stopText: null
19 | });
20 |
21 | Object.assign(MediaElementPlayer.prototype, {
22 |
23 | /**
24 | * Feature constructor.
25 | *
26 | * Always has to be prefixed with `build` and the name that will be used in MepDefaults.features list
27 | * @param {MediaElementPlayer} player
28 | * @param {HTMLElement} controls
29 | * @param {HTMLElement} layers
30 | * @param {HTMLElement} media
31 | */
32 | buildstop (player, controls, layers, media) {
33 | const
34 | t = this,
35 | stopTitle = mejs.Utils.isString(t.options.stopText) ? t.options.stopText : mejs.i18n.t('mejs.stop'),
36 | button = document.createElement('div')
37 | ;
38 |
39 | button.className = `${t.options.classPrefix}button ${t.options.classPrefix}stop-button ${t.options.classPrefix}stop`;
40 | button.innerHTML = ` `;
41 |
42 | t.addControlElement(button, 'stop');
43 |
44 | button.addEventListener('click', () => {
45 | if (typeof media.stop === 'function') {
46 | media.stop();
47 | } else if (media.readyState > 0) {
48 | if (!media.paused) {
49 | media.pause();
50 | }
51 |
52 | media.setSrc('');
53 | media.load();
54 |
55 | const playButton = controls.querySelector(`.${t.options.classPrefix}playpause-button`);
56 | mejs.Utils.removeClass(playButton, `${t.options.classPrefix}pause`);
57 | mejs.Utils.addClass(playButton, `${t.options.classPrefix}play`);
58 |
59 | // It will throw an error trying to load an empty source, so remove it since it's expected
60 | if (t.container.querySelector(`.${t.options.classPrefix}cannotplay`)) {
61 | t.container.querySelector(`.${t.options.classPrefix}cannotplay`).remove();
62 | layers.querySelector(`.${t.options.classPrefix}overlay-error`).parentNode.style.display = 'none';
63 | layers.querySelector(`.${t.options.classPrefix}overlay-error`).remove();
64 | }
65 | }
66 |
67 | const event = mejs.Utils.createEvent('timeupdate', media);
68 | media.dispatchEvent(event);
69 | });
70 | }
71 | });
--------------------------------------------------------------------------------
/src/stop/stop.svg:
--------------------------------------------------------------------------------
1 | 4
2 |
--------------------------------------------------------------------------------
/src/vrview/cardboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mediaelement/mediaelement-plugins/6b5de466fd9676c1287fc0c34111843813bc2a77/src/vrview/cardboard.png
--------------------------------------------------------------------------------
/src/vrview/cardboard.svg:
--------------------------------------------------------------------------------
1 | 6
--------------------------------------------------------------------------------
/src/vrview/vrview.css:
--------------------------------------------------------------------------------
1 | .mejs__vrview-button > button,
2 | .mejs-vrview-button > button {
3 | background: url('cardboard.svg') no-repeat 0 4px;
4 | }
--------------------------------------------------------------------------------