├── .gitignore
├── src
├── fonts
│ ├── stvideo.eot
│ ├── stvideo.ttf
│ ├── stvideo.woff
│ ├── stvideo.woff2
│ ├── fontello-config.json
│ └── stvideo.svg
├── css
│ └── stvideo.css
└── js
│ └── stvideo.js
├── dist
├── fonts
│ ├── stvideo.eot
│ ├── stvideo.ttf
│ ├── stvideo.woff
│ ├── stvideo.woff2
│ ├── fontello-config.json
│ └── stvideo.svg
├── css
│ └── stvideo.css
└── js
│ ├── stvideo.min.js
│ ├── stvideo.min.js.map
│ └── stvideo.js
├── .editorconfig
├── package.json
├── .eslintrc.json
├── README.md
└── gruntfile.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /__stuff
3 | *.DS_Store
4 |
5 | /assets
6 | /index.html
7 |
--------------------------------------------------------------------------------
/src/fonts/stvideo.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/src/fonts/stvideo.eot
--------------------------------------------------------------------------------
/src/fonts/stvideo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/src/fonts/stvideo.ttf
--------------------------------------------------------------------------------
/dist/fonts/stvideo.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/dist/fonts/stvideo.eot
--------------------------------------------------------------------------------
/dist/fonts/stvideo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/dist/fonts/stvideo.ttf
--------------------------------------------------------------------------------
/dist/fonts/stvideo.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/dist/fonts/stvideo.woff
--------------------------------------------------------------------------------
/src/fonts/stvideo.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/src/fonts/stvideo.woff
--------------------------------------------------------------------------------
/src/fonts/stvideo.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/src/fonts/stvideo.woff2
--------------------------------------------------------------------------------
/dist/fonts/stvideo.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tstabla/stVideo/HEAD/dist/fonts/stvideo.woff2
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = tab
6 | indent_size = 2
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stVideo",
3 | "version": "0.9.0",
4 | "description": "HTML5 video canvas player. Prevents video fullscreen on iPhone/iPad.",
5 | "author": {
6 | "name": "Tomasz Stabla",
7 | "email": "t.stabla@hotmail.com",
8 | "url": "http://stabla.com"
9 | },
10 | "main": "dist/js/stVideo.js",
11 | "homepage": "https://github.com/tstabla/stVideo",
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/tstabla/stVideo.git"
15 | },
16 | "license": "MIT",
17 | "keywords": [
18 | "html5",
19 | "video",
20 | "canvas",
21 | "player",
22 | "simple",
23 | "iphone",
24 | "ipad"
25 | ],
26 | "dependencies": {
27 | },
28 | "devDependencies": {
29 | "grunt": "~0.4.2",
30 | "grunt-contrib-copy": "*",
31 | "grunt-contrib-concat": "*",
32 | "grunt-contrib-jshint": "*",
33 | "grunt-contrib-uglify": "*",
34 | "grunt-contrib-watch": "*",
35 | "matchdep": "*",
36 | "module": "0.0.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/dist/fonts/fontello-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "css_prefix_text": "icon-",
4 | "css_use_suffix": false,
5 | "hinting": true,
6 | "units_per_em": 1000,
7 | "ascent": 850,
8 | "glyphs": [
9 | {
10 | "uid": "8489d61496923b1159b01d8a0a7b2df0",
11 | "css": "volume-off",
12 | "code": 59392,
13 | "src": "elusive"
14 | },
15 | {
16 | "uid": "5d9730dc93976d27eb07914eab50a507",
17 | "css": "volume-down",
18 | "code": 59393,
19 | "src": "elusive"
20 | },
21 | {
22 | "uid": "b59b3b618699b467541f631edd5a02ed",
23 | "css": "volume",
24 | "code": 59394,
25 | "src": "elusive"
26 | },
27 | {
28 | "uid": "012ff5762ccb18c16bdfdd6baf187406",
29 | "css": "volume-up",
30 | "code": 59395,
31 | "src": "elusive"
32 | },
33 | {
34 | "uid": "3711151b8b34536498e2a7f4d5188ed2",
35 | "css": "play",
36 | "code": 61455,
37 | "src": "mfglabs"
38 | },
39 | {
40 | "uid": "164f35b55c3346b03fa89a711a4f3980",
41 | "css": "pause",
42 | "code": 61454,
43 | "src": "mfglabs"
44 | }
45 | ]
46 | }
--------------------------------------------------------------------------------
/src/fonts/fontello-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "css_prefix_text": "icon-",
4 | "css_use_suffix": false,
5 | "hinting": true,
6 | "units_per_em": 1000,
7 | "ascent": 850,
8 | "glyphs": [
9 | {
10 | "uid": "8489d61496923b1159b01d8a0a7b2df0",
11 | "css": "volume-off",
12 | "code": 59392,
13 | "src": "elusive"
14 | },
15 | {
16 | "uid": "5d9730dc93976d27eb07914eab50a507",
17 | "css": "volume-down",
18 | "code": 59393,
19 | "src": "elusive"
20 | },
21 | {
22 | "uid": "b59b3b618699b467541f631edd5a02ed",
23 | "css": "volume",
24 | "code": 59394,
25 | "src": "elusive"
26 | },
27 | {
28 | "uid": "012ff5762ccb18c16bdfdd6baf187406",
29 | "css": "volume-up",
30 | "code": 59395,
31 | "src": "elusive"
32 | },
33 | {
34 | "uid": "3711151b8b34536498e2a7f4d5188ed2",
35 | "css": "play",
36 | "code": 61455,
37 | "src": "mfglabs"
38 | },
39 | {
40 | "uid": "164f35b55c3346b03fa89a711a4f3980",
41 | "css": "pause",
42 | "code": 61454,
43 | "src": "mfglabs"
44 | }
45 | ]
46 | }
--------------------------------------------------------------------------------
/dist/fonts/stvideo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/fonts/stvideo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es6": true,
6 | "node": true,
7 | "mocha": true
8 | },
9 | "extends": "eslint:recommended",
10 | "parserOptions": {
11 | "sourceType": "module",
12 | "ecmaFeatures": {
13 | "impliedStrict": true
14 | }
15 | },
16 | "rules": {
17 | "indent": [ 2, 2 ],
18 | "linebreak-style": [ 2, "unix" ],
19 | "quotes": [ 2, "single" ],
20 | "semi": [ 2, "always" ],
21 | "curly": 2,
22 | "brace-style": [2, "1tbs" ],
23 | "camelcase": [ 2, { "properties": "always" } ],
24 | "comma-spacing": [ 2, { "before": false, "after": true } ],
25 | "comma-style": [ 2, "last" ],
26 | "key-spacing": [ 2, { "align": { "beforeColon": true, "afterColon": true, "on": "colon" } } ],
27 | "keyword-spacing": 2,
28 | "block-spacing": 2,
29 | "array-bracket-spacing": [ 2, "always" ],
30 | "object-curly-spacing": [ 2, "always" ],
31 | "computed-property-spacing": [ 2, "always" ],
32 | "space-in-parens": [ 2, "always" ],
33 | "space-before-function-paren": [ 2, "never" ],
34 | "generator-star-spacing": [ 2, "after" ],
35 | "yield-star-spacing": [ 2, "after" ],
36 | "space-infix-ops": 2,
37 | "space-unary-ops": 2,
38 | "spaced-comment": [ 2, "always" ],
39 | "arrow-spacing": [2, { "before": true, "after": true } ],
40 | "arrow-parens": [ 2, "always" ],
41 | "arrow-body-style": [ 2, "always" ],
42 | "no-trailing-spaces": 2,
43 | "no-multiple-empty-lines": [ 2, { "max": 1 } ],
44 | "eol-last": 2,
45 | "valid-jsdoc": 2,
46 | "no-implicit-coercion": [ 2, { "allow": [ "!!" ] } ],
47 | "no-native-reassign": 2,
48 | "wrap-iife": [ 2, "any" ],
49 | "yoda": [ 2, "never" ],
50 | "prefer-const": 2,
51 | "prefer-rest-params": 2,
52 | "prefer-spread": 2,
53 | "object-shorthand": [ 2, "always" ],
54 | "no-array-constructor": 2,
55 | "no-new-object": 2,
56 | "new-cap": 2,
57 | "new-parens": 2,
58 | "no-lonely-if": 2,
59 | "no-use-before-define": 2,
60 | "no-with": 2,
61 | "eqeqeq": [ 2, "smart" ],
62 | "no-unused-vars": [2, {"vars": "all", "args": "none"}]
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [stVideo](https://tstabla.github.io/stVideo/)
2 | HTML5 video canvas player. Prevents video fullscreen on iPhone/iPad.
3 |
4 | [SEE DEMO](https://tstabla.github.io/stVideo/)
5 |
6 | ## How to use
7 |
8 | Just create div where canvas or video element will be inserted.
9 | Optionally you can add attribute with params.
10 |
11 | ```html
12 |
13 | ```
14 |
15 | Then create new object.
16 |
17 | ```javascript
18 | var video = new stVideo( '#player' );
19 | ```
20 |
21 | Or create new object with params, if you not added them to HTML element.
22 |
23 | ```javascript
24 | var video = new stVideo( '#player', {
25 | "mp4" : "filename.mp4", //recommended
26 | "webm" : "filename.webm", //recommended
27 | "ogg" : "filename.ogg",
28 | "width" : 524, //required
29 | "height": 270, //required
30 | "force" : "", //'video' or 'canvas',
31 | "framesPerSecond": 30, //needed for canvas refresh, default 30
32 | "volume": 1 //default
33 | } );
34 | ```
35 |
36 | Look at the table below, and best use .mp4 and .webm video files format.
37 |
38 | | | .mp4 | .webm | .ogg |
39 | | --- | :---: | :---: | :---: |
40 | | Android | X | | X |
41 | | iPhone | X | | |
42 | | Firefox | | X | X |
43 | | Chrome | | X | X |
44 | | Safari | X | | |
45 | | IE >= 9 | X | | |
46 | | IE Mobile | X | | |
47 |
48 |
49 | At the end, you can play video immediately after initialization.
50 |
51 | ```javascript
52 | video.on( 'canplaythrough', function() {
53 | video.play();
54 | } );
55 | ```
56 |
57 | You can attach other events from list http://www.w3.org/TR/html5/embedded-content-0.html#mediaevents but some of them may not work properly with canvas video for ex. "volumechange".
58 |
59 | Examples:
60 |
61 | ```javascript
62 | video.on( 'play', function() {
63 | console.log( 'play' );
64 | } );
65 |
66 | video.on( 'pause', function() {
67 | console.log( 'pause' );
68 | } );
69 |
70 | video.on( 'end', function() {
71 | console.log( 'end' );
72 | } );
73 | ```
74 |
75 | ## Events
76 |
77 | ```javascript
78 | video.play(); //play video
79 |
80 | video.pause(); //pause video
81 |
82 | video.on( 'name', function(){} ); //for attach event
83 |
84 | video.destroy(); //not working - future function to remove player
85 | ```
86 |
--------------------------------------------------------------------------------
/gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt){
2 |
3 | require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
4 |
5 | grunt.initConfig({
6 |
7 | pkg: grunt.file.readJSON('package.json'),
8 |
9 | paths: {
10 | 'dist': 'dist',
11 | 'src': 'src',
12 | },
13 |
14 | copyright: '/*! \n' +
15 | ' * <%= pkg.name %> \n' +
16 | ' * <%= pkg.description %>\n' +
17 | ' * \n' +
18 | ' * Licensed under the MIT license: \n' +
19 | ' * http://www.opensource.org/licenses/mit-license.php \n' +
20 | ' * \n' +
21 | ' * Any and all use of this script must be accompanied by this copyright/license notice in its present form. \n' +
22 | ' * \n' +
23 | ' * Version: <%= pkg.version %>\n' +
24 | ' * Author: <%= pkg.author.name %> <<%= pkg.author.email %>> (<%= pkg.author.url %>)\n' +
25 | ' * Site: <%= pkg.homepage %>/\n' +
26 | ' */\n' +
27 | '',
28 |
29 | jshint: {
30 | src: {
31 | options: {
32 | '-W099': true,
33 | expr: true
34 | },
35 | src: [
36 | 'gruntfile.js',
37 | '<%= paths.src %>/js/**/*.js'
38 | ]
39 | }
40 | },
41 |
42 | concat: {
43 | options: {
44 | separator: ';',
45 | banner: '<%= copyright %>'
46 | },
47 | dist: {
48 | src: ['<%= paths.src %>/js/stvideo.js'],
49 | dest: '<%= paths.dist %>/js/stvideo.js'
50 | }
51 | },
52 |
53 | copy : {
54 | files: {
55 | expand: true,
56 | cwd: '<%= paths.src %>',
57 | src: ['**/fonts/**', '**/css/**'],
58 | dest: '<%= paths.dist %>/'
59 | }
60 | },
61 |
62 | uglify: {
63 | dist: {
64 | options: {
65 | report: 'min',
66 | banner: '<%= copyright %>',
67 | sourceMap: true,
68 | },
69 | files: [{
70 | '<%= paths.dist %>/js/stvideo.min.js': ['<%= paths.dist %>/js/stvideo.js']
71 | }],
72 | }
73 | },
74 |
75 | watch: {
76 | js: {
77 | files: [
78 | '<%= paths.src %>/js/**/*.js',
79 | ],
80 | tasks: ['buildjs']
81 | },
82 | css: {
83 | files: [
84 | '<%= paths.src %>/css/**',
85 | ],
86 | tasks: ['copy']
87 | }
88 | }
89 | });
90 |
91 | grunt.registerTask('default', [
92 | 'copy', 'buildjs', 'watch'
93 | ]);
94 |
95 | grunt.registerTask('build', [
96 | 'copy', 'buildjs'
97 | ]);
98 |
99 | grunt.registerTask('buildjs', [
100 | 'jshint', 'concat', 'uglify',
101 | ]);
102 |
103 |
104 | };
105 |
--------------------------------------------------------------------------------
/dist/css/stvideo.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'stvideo';
3 | src: url('../fonts/stvideo.eot?21066397');
4 | src: url('../fonts/stvideo.eot?21066397#iefix') format('embedded-opentype'),
5 | url('../fonts/stvideo.woff2?21066397') format('woff2'),
6 | url('../fonts/stvideo.woff?21066397') format('woff'),
7 | url('../fonts/stvideo.ttf?21066397') format('truetype'),
8 | url('../fonts/stvideo.svg?21066397#fontello') format('svg');
9 | font-weight: normal;
10 | font-style: normal;
11 | }
12 |
13 | /*volume-off { content: '\e800'; }*/
14 | /*volume-down { content: '\e801'; }*/
15 | /*volume { content: '\e802'; }*/
16 | /*volume-up { content: '\e803'; }*/
17 | /*pause { content: '\f00e'; }*/
18 | /*play { content: '\f00f'; }*/
19 |
20 |
21 | .stvideo-box {
22 | margin: 0 auto;
23 | width: 100%;
24 | max-width: 524px;
25 | position: relative;
26 | }
27 |
28 | .stvideo-box * {
29 | margin: 0;
30 | padding: 0;
31 | }
32 |
33 | .stvideo-box *:before {
34 | font-weight: 400;
35 | -webkit-font-smoothing: antialiased;
36 | -moz-osx-font-smoothing: grayscale;
37 | }
38 |
39 | .stvideo-box__player {
40 | padding-bottom: 56.25%;
41 | width: 100%;
42 | height: 0;
43 | position: relative;
44 | }
45 |
46 | .stvideo-box video,
47 | .stvideo-box canvas {
48 | width: 100%;
49 | height: 100%;
50 | position: absolute;
51 | top: 0; left: 0;
52 | }
53 |
54 | .stvideo-box__play {
55 | cursor: pointer;
56 | margin-top: -5%;
57 | margin-left: -5%;
58 | padding-bottom: 10%;
59 | width: 10%;
60 | height: 0;
61 | position: absolute;
62 | top: 50%; left: 50%;
63 | z-index: 5;
64 | background: rgba(236,240,241,0.95);
65 | border-radius: 100%;
66 | transition: opacity 0.3s linear, visibility 0s linear 0.3s;
67 | }
68 |
69 | .stvideo-box__play:before {
70 | content: '\f00f';
71 | font-size: 24px;
72 | line-height: 1;
73 | font-family: stvideo;
74 | color: #1bb592;
75 | margin-left: 2px;
76 | position: absolute;
77 | top: 50%; left: 50%;
78 | -ms-transform: translate(-50%, -50%);
79 | transform: translate(-50%, -50%);
80 | transition: color 0.3s linear;
81 | }
82 |
83 | .stvideo-box__play:hover:before {
84 | color: #179d7e;
85 | }
86 |
87 | .stvideo-box--is-playing .stvideo-box__play {
88 | opacity: 0;
89 | visibility: hidden;
90 | }
91 |
92 | .stvideo-box__controls {
93 | padding: 12px 94px 12px 48px;
94 | width: 100%;
95 | position: absolute;
96 | bottom: 0; left: 0;
97 | z-index: 5;
98 | background: #253244;
99 | box-sizing: border-box;
100 | }
101 |
102 | .stvideo-box--has-audio .stvideo-box__controls {
103 | padding-left: 73px;
104 | }
105 |
106 |
107 | .stvideo-box__play-pause {
108 | cursor: pointer;
109 | position: absolute;
110 | top: 10px; left: 12px;
111 | }
112 |
113 | .stvideo-box__play-pause:before {
114 | content: '\f00f';
115 | font-size: 16px;
116 | line-height: 1;
117 | font-family: stvideo;
118 | color: #1bb592;
119 | }
120 |
121 | .stvideo-box__play-pause:hover:before {
122 | color: #179d7e;
123 | }
124 |
125 | .stvideo-box--is-playing .stvideo-box__play-pause:before {
126 | content: '\f00e';
127 | }
128 |
129 | .stvideo-box__timeline {
130 | width: 100%;
131 | height: 12px;
132 | position: relative;
133 | background: #ecf0f1;
134 | border-radius: 5px;
135 | }
136 |
137 | .stvideo-box__progress {
138 | width: 0;
139 | height: 100%;
140 | background: #1abc9c;
141 | border-radius: 5px;
142 | transition: width 0.15s linear;
143 | }
144 |
145 | .stvideo-box__handle {
146 | margin: -2px 0 0 -8px;
147 | width: 16px;
148 | height: 16px;
149 | position: absolute;
150 | top: 0; left: 0;
151 | background: #1b9f80;
152 | border-radius: 100%;
153 | }
154 |
155 | .stvideo-box__duration {
156 | font-size: 12px;
157 | line-height: 1;
158 | font-weight: 600;
159 | font-family: Arial, Helvetica, sans-serif;
160 | color: #fff;
161 | -webkit-font-smoothing: antialiased;
162 | -moz-osx-font-smoothing: grayscale;
163 | position: absolute;
164 | top: 12px; right: 8px;
165 | }
166 |
167 | .stvideo-box__volume {
168 | display: none;
169 | cursor: pointer;
170 | position: absolute;
171 | top: 10px; left: 40px;
172 | }
173 |
174 | .stvideo-box__volume:before {
175 | content: '\e802';
176 | font-size: 16px;
177 | line-height: 1;
178 | font-family: stvideo;
179 | color: rgba(236,240,241,0.95);
180 | }
181 |
182 | .stvideo-box--has-audio .stvideo-box__volume {
183 | display: block;
184 | }
185 |
186 | .stvideo-box--is-muted .stvideo-box__volume:before {
187 | content: '\e800';
188 | }
189 |
--------------------------------------------------------------------------------
/src/css/stvideo.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'stvideo';
3 | src: url('../fonts/stvideo.eot?21066397');
4 | src: url('../fonts/stvideo.eot?21066397#iefix') format('embedded-opentype'),
5 | url('../fonts/stvideo.woff2?21066397') format('woff2'),
6 | url('../fonts/stvideo.woff?21066397') format('woff'),
7 | url('../fonts/stvideo.ttf?21066397') format('truetype'),
8 | url('../fonts/stvideo.svg?21066397#fontello') format('svg');
9 | font-weight: normal;
10 | font-style: normal;
11 | }
12 |
13 | /*volume-off { content: '\e800'; }*/
14 | /*volume-down { content: '\e801'; }*/
15 | /*volume { content: '\e802'; }*/
16 | /*volume-up { content: '\e803'; }*/
17 | /*pause { content: '\f00e'; }*/
18 | /*play { content: '\f00f'; }*/
19 |
20 |
21 | .stvideo-box {
22 | margin: 0 auto;
23 | width: 100%;
24 | max-width: 524px;
25 | position: relative;
26 | }
27 |
28 | .stvideo-box * {
29 | margin: 0;
30 | padding: 0;
31 | }
32 |
33 | .stvideo-box *:before {
34 | font-weight: 400;
35 | -webkit-font-smoothing: antialiased;
36 | -moz-osx-font-smoothing: grayscale;
37 | }
38 |
39 | .stvideo-box__player {
40 | padding-bottom: 56.25%;
41 | width: 100%;
42 | height: 0;
43 | position: relative;
44 | }
45 |
46 | .stvideo-box video,
47 | .stvideo-box canvas {
48 | width: 100%;
49 | height: 100%;
50 | position: absolute;
51 | top: 0; left: 0;
52 | }
53 |
54 | .stvideo-box__play {
55 | cursor: pointer;
56 | margin-top: -5%;
57 | margin-left: -5%;
58 | padding-bottom: 10%;
59 | width: 10%;
60 | height: 0;
61 | position: absolute;
62 | top: 50%; left: 50%;
63 | z-index: 5;
64 | background: rgba(236,240,241,0.95);
65 | border-radius: 100%;
66 | transition: opacity 0.3s linear, visibility 0s linear 0.3s;
67 | }
68 |
69 | .stvideo-box__play:before {
70 | content: '\f00f';
71 | font-size: 24px;
72 | line-height: 1;
73 | font-family: stvideo;
74 | color: #1bb592;
75 | margin-left: 2px;
76 | position: absolute;
77 | top: 50%; left: 50%;
78 | -ms-transform: translate(-50%, -50%);
79 | transform: translate(-50%, -50%);
80 | transition: color 0.3s linear;
81 | }
82 |
83 | .stvideo-box__play:hover:before {
84 | color: #179d7e;
85 | }
86 |
87 | .stvideo-box--is-playing .stvideo-box__play {
88 | opacity: 0;
89 | visibility: hidden;
90 | }
91 |
92 | .stvideo-box__controls {
93 | padding: 12px 94px 12px 48px;
94 | width: 100%;
95 | position: absolute;
96 | bottom: 0; left: 0;
97 | z-index: 5;
98 | background: #253244;
99 | box-sizing: border-box;
100 | }
101 |
102 | .stvideo-box--has-audio .stvideo-box__controls {
103 | padding-left: 73px;
104 | }
105 |
106 |
107 | .stvideo-box__play-pause {
108 | cursor: pointer;
109 | position: absolute;
110 | top: 10px; left: 12px;
111 | }
112 |
113 | .stvideo-box__play-pause:before {
114 | content: '\f00f';
115 | font-size: 16px;
116 | line-height: 1;
117 | font-family: stvideo;
118 | color: #1bb592;
119 | }
120 |
121 | .stvideo-box__play-pause:hover:before {
122 | color: #179d7e;
123 | }
124 |
125 | .stvideo-box--is-playing .stvideo-box__play-pause:before {
126 | content: '\f00e';
127 | }
128 |
129 | .stvideo-box__timeline {
130 | width: 100%;
131 | height: 12px;
132 | position: relative;
133 | background: #ecf0f1;
134 | border-radius: 5px;
135 | }
136 |
137 | .stvideo-box__progress {
138 | width: 0;
139 | height: 100%;
140 | background: #1abc9c;
141 | border-radius: 5px;
142 | transition: width 0.15s linear;
143 | }
144 |
145 | .stvideo-box__handle {
146 | margin: -2px 0 0 -8px;
147 | width: 16px;
148 | height: 16px;
149 | position: absolute;
150 | top: 0; left: 0;
151 | background: #1b9f80;
152 | border-radius: 100%;
153 | }
154 |
155 | .stvideo-box__duration {
156 | font-size: 12px;
157 | line-height: 1;
158 | font-weight: 600;
159 | font-family: Arial, Helvetica, sans-serif;
160 | color: #fff;
161 | -webkit-font-smoothing: antialiased;
162 | -moz-osx-font-smoothing: grayscale;
163 | position: absolute;
164 | top: 12px; right: 8px;
165 | }
166 |
167 | .stvideo-box__volume {
168 | display: none;
169 | cursor: pointer;
170 | position: absolute;
171 | top: 10px; left: 40px;
172 | }
173 |
174 | .stvideo-box__volume:before {
175 | content: '\e802';
176 | font-size: 16px;
177 | line-height: 1;
178 | font-family: stvideo;
179 | color: rgba(236,240,241,0.95);
180 | }
181 |
182 | .stvideo-box--has-audio .stvideo-box__volume {
183 | display: block;
184 | }
185 |
186 | .stvideo-box--is-muted .stvideo-box__volume:before {
187 | content: '\e800';
188 | }
189 |
--------------------------------------------------------------------------------
/dist/js/stvideo.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * stVideo
3 | * HTML5 video canvas player. Prevents video fullscreen on iPhone/iPad.
4 | *
5 | * Licensed under the MIT license:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Any and all use of this script must be accompanied by this copyright/license notice in its present form.
9 | *
10 | * Version: 0.9.0
11 | * Author: Tomasz Stabla (http://stabla.com)
12 | * Site: https://github.com/tstabla/stVideo/
13 | */
14 |
15 | !function(a,b){"function"==typeof define&&define.amd?define([],function(){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(a):a.stVideo=b(a)}("undefined"!=typeof global?global:this.window||this.global,function(a){"use strict";!function(a){for(var b=0,c=["ms","moz","webkit","o"],d=0;d=10&&c.setAttribute("playsinline",""),a=this.supportedVideoFormat(c),!a||this.useCanvas&&!this.settings.mp4||!this.settings[a.ext]?void this.error.badVideoFormat.call(this):(d=document.createElement("source"),d.setAttribute("src",this.settings[a.ext]),d.setAttribute("type",a.type),c.appendChild(d),b=document.createElement("div"),b.classList.add(this.classNames.player),this.useCanvas?(e=document.createElement("canvas"),e.setAttribute("width",this.settings.width),e.setAttribute("height",this.settings.height),f=e.getContext("2d"),f.fillStyle="#ffffff",f.fillRect(0,0,this.settings.width,this.settings.height),f.drawImage(c,0,0,this.settings.width,this.settings.height),this.canvasContext=f,b.appendChild(e)):b.appendChild(c),this.element.appendChild(b),c.load(),this.video=c,this.playerControls(),this.addVideoListeners(),this.addControlsListeners(),void(this.isMobile?window.addEventListener("orientationchange",function(){this.resizeTo&&clearTimeout(this.resizeTo),this.resizeTo=setTimeout(function(){for(g=0;g.01?b.changeState("muted",!1):b.changeState("muted",!0)}),b.eventsVideoCollection.push(a),this.video.addEventListener("error",a=function(a){b.isError=!0,b.error.custom(a)}),b.eventsVideoCollection.push(a)},b.prototype.addControlsListeners=function(a){var b,c=this;this.elPlay.addEventListener("click",b=function(){c.isPlaying?c.pause():c.play()}),c.eventsControlsCollection.push(b),this.elPlayPause.addEventListener("click",b=function(){c.isPlaying?c.pause():c.play()}),c.eventsControlsCollection.push(b),this.useTouch?(this.elHandle.addEventListener("touchstart",b=function(a){a.stopPropagation(),c.timelineSettings.isHandleMoving=!0,c.timelineSettings.touchObj=a.changedTouches[0],c.timelineSettings.posLeft=c.timelineSettings.lastPosLeft,c.timelineSettings.startX=parseInt(c.timelineSettings.touchObj.clientX),c.changeState("handle",!0)},!1),c.eventsControlsCollection.push(b),this.elHandle.addEventListener("touchmove",b=function(a){if(c.timelineSettings.isHandleMoving){a.stopPropagation(),c.timelineSettings.touchObj=a.changedTouches[0];var b=parseInt(c.timelineSettings.touchObj.clientX)-c.timelineSettings.startX;c.moveHandle(b)}},!1),c.eventsControlsCollection.push(b),this.elHandle.addEventListener("touchend",b=function(a){a.preventDefault(),c.timelineSettings.posLeft=c.timelineSettings.lastPosLeft,c.moveHandle(0,!0),c.changeState("handle",!1),c.timelineSettings.isHandleMoving=!1},!1),c.eventsControlsCollection.push(b)):(document.body.addEventListener("mousedown",b=function(a){if(a.preventDefault(),c.timelineSettings.isHandleMoving=!0,c.isContained(c.elHandle,a))c.timelineSettings.touchObj=a,c.timelineSettings.posLeft=c.timelineSettings.lastPosLeft,c.timelineSettings.startX=parseInt(a.clientX),c.timelineSettings.isMouseDown=!0,c.changeState("handle",!0);else if(c.isContained(c.elTimeline,a)){c.timelineSettings.touchObj=a,c.timelineSettings.posLeft=0,c.timelineSettings.startX=parseInt(a.layerX);var b=c.timelineSettings.startX;c.moveHandle(b,!0),c.timelineSettings.isHandleMoving=!1}else c.timelineSettings.isHandleMoving=!1},!1),c.eventsControlsCollection.push(b),document.body.addEventListener("mousemove",b=function(a){if(a.preventDefault(),c.timelineSettings.isMouseDown&&c.timelineSettings.isHandleMoving){c.timelineSettings.touchObj=a;var b=parseInt(c.timelineSettings.touchObj.clientX)-c.timelineSettings.startX;c.moveHandle(b)}},!1),c.eventsControlsCollection.push(b),document.body.addEventListener("mouseup",b=function(a){a.preventDefault(),c.timelineSettings.isMouseDown&&(c.timelineSettings.touchObj=a,c.timelineSettings.posLeft=c.timelineSettings.lastPosLeft,c.timelineSettings.startX=parseInt(c.timelineSettings.touchObj.clientX),c.timelineSettings.isMouseDown=!1,c.moveHandle(0,!0),c.changeState("handle",!1),c.timelineSettings.isHandleMoving=!1)},!1),c.eventsControlsCollection.push(b))},b.prototype.canvasAudio=function(){this.audio=document.createElement("audio"),this.audio.innerHTML=this.video.innerHTML,this.audio.load()},b.prototype.canvasControl=function(b){"play"===b||"play"===b&&this.isEnded?(this.isEnded&&(this.changeState("end",!1),this.video.currentTime=0,this.audio&&(this.audio.currentTime=0),this.lastTime=Date.now()),this.audio&&this.isMuted!==!0&&this.audio.play(),this.changeState("play",!0),this.animationFrame=a.requestAnimationFrame(this.canvasFrameUpdate.bind(this))):"pause"!==b&&"ended"!==b||("ended"===b?this.changeState("end",!0):this.changeState("pause",!0),this.audio&&this.audio.pause(),this.changeState("play",!1),a.cancelAnimationFrame(this.animationFrame))},b.prototype.canvasFrameUpdate=function(){var b=Date.now(),c=(b-(this.lastTime||b))/1e3;(!c||c>=1/this.settings.framesPerSecond)&&(this.video.currentTime=this.video.currentTime+c,this.lastTime=b),this.video.currentTime>=this.video.duration?this.canvasControl("ended"):this.animationFrame=a.requestAnimationFrame(this.canvasFrameUpdate.bind(this))},b.prototype.canvasDrawFrame=function(){this.canvasContext.drawImage(this.video,0,0,this.settings.width,this.settings.height)},b.prototype.progressUpdate=function(a){var b=this.video.currentTime,c=this.video.duration,d=this.timelineSettings;a&&(b=this.video.currentTime=a/d.wrapperWidth*c);var e=(b/c*d.wrapperWidth).toFixed(2);e<0?e=0:e>d.wrapperWidth&&(e=d.wrapperWidth),this.elProgress.style.width=+e+"px",d.isHandleMoving||(this.elHandle.style.left=+e+"px"),this.elDuration.innerText=this.formatTime(b)+" / "+this.formatTime(c)},b.prototype.formatTime=function(a){var b,c;return b=Math.floor(a/60),b=b>=10?b:"0"+b,c=Math.floor(a%60),c=c>=10?c:"0"+c,b+":"+c},b.prototype.moveHandle=function(a,b){var c=this.timelineSettings;if(c.isHandleMoving){var d=(b?c.lastDistance:a)>0?"right":"left",e=c.posLeft+a;e<0?e=0:e>c.wrapperWidth&&(e=c.wrapperWidth),this.elHandle.style.left=e+"px",c.lastPosLeft=e,c.lastDistance=a,c.lastDirection=d,b&&this.progressUpdate(e)}},b.prototype.error={badVideoFormat:function(){this.useCanvas?console.error("Apple devices support only .mp4 format"):console.error("Best use .webm and .mp4 video formats"),this.element.classList.add(this.classNames.error)},checkSettings:function(){console.error("Check all required settings"),this.element.classList.add(this.classNames.error)},custom:function(a){console.error(a),this.element.classList.add(this.classNames.error)}},b.prototype.on=function(a,b){if(!this.isError){var c,d=this;this.video.addEventListener(a,c=function(){b.call(this)}),c.fnName=a,d.eventsUserCollection.push(c)}},b.prototype.eventCallback=function(a){if(this.useCanvas)for(var b in this.eventsUserCollection)this.eventsUserCollection[b].fnName===a&&this.eventsUserCollection[b]()},b.prototype.play=function(){this.isError||(this.lastTime=Date.now(),this.useCanvas?this.canvasControl("play"):this.video.play())},b.prototype.pause=function(){this.isError||this.isPlaying&&(this.useCanvas?this.canvasControl("pause"):this.video.pause())},b.prototype.changeState=function(a,b){var c=this.element.classList;"play"===a&&(this.isPlaying=b,b?(c.add(this.classNames.isPlaying),this.eventCallback("play")):c.remove(this.classNames.isPlaying)),"pause"===a&&(this.isPaused=b,b?(c.add(this.classNames.isPaused),this.eventCallback("pause")):c.remove(this.classNames.isPaused)),"end"===a&&(this.isEnded=b,b?(c.add(this.classNames.isEnded),this.eventCallback("end")):c.remove(this.classNames.isEnded)),"muted"===a&&(this.isMuted=b,b?(c.add(this.classNames.isMuted),this.eventCallback("muted")):c.remove(this.classNames.isMuted)),"handle"===a&&(this.isMuted=b,b?c.add(this.classNames.isHandle):c.remove(this.classNames.isHandle))},b.prototype.destroy=function(){},b});
16 | //# sourceMappingURL=stvideo.min.js.map
--------------------------------------------------------------------------------
/dist/js/stvideo.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["stvideo.js"],"names":["root","factory","define","amd","module","exports","stVideo","global","this","window","lastTime","vendors","x","length","requestAnimationFrame","cancelAnimationFrame","callback","element","currTime","Date","getTime","timeToCall","Math","max","id","setTimeout","clearTimeout","el","settings","iOS","test","navigator","userAgent","iOSv","parseFloat","exec","replace","useCanvas","isMobile","match","useTouch","document","documentElement","ontouchstart","onmsgesturechange","DocumentTouch","querySelector","defaults","force","framesPerSecond","volume","getSettings","mp4","webm","ogg","width","height","classNames","init","error","isPlaying","isPaused","isEnded","isMuted","isHandle","hasAudio","player","poster","play","playPause","controls","timeline","progress","handle","duration","timelineSettings","wrapperWidth","isMouseDown","isHandleMoving","startX","touchObj","posLeft","lastPosLeft","lastDistance","lastDirection","eventsUserCollection","eventsVideoCollection","eventsControlsCollection","initPlayer","isError","checkSettings","prototype","attr","options","key","getAttribute","JSON","parse","hasOwnProperty","isContained","m","ev","e","event","c","type","target","relatedTarget","fromElement","toElement","parentNode","er","format","wrapper","video","videoSource","canvas","canvasContext","itemIndex","self","classList","add","createElement","setAttribute","supportedVideoFormat","ext","badVideoFormat","call","appendChild","getContext","fillStyle","fillRect","drawImage","load","playerControls","addVideoListeners","addControlsListeners","addEventListener","resizeTo","resizeCacheArr","resizeHandler","fn","push","canPlayType","videoAudio","tempEvent","mozHasAudio","Boolean","webkitAudioDecodedByteCount","audioTracks","elControls","elVolume","audio","currentTime","changeState","pause","style","backgroundImage","elPlay","elPlayPause","elTimeline","elProgress","elHandle","elDuration","canvasAudio","canvasDrawFrame","progressUpdate","offsetWidth","custom","controlsBox","stopPropagation","changedTouches","parseInt","clientX","dist","moveHandle","preventDefault","body","layerX","innerHTML","canvasControl","action","now","animationFrame","canvasFrameUpdate","bind","time","elapsed","movedByDistance","current","toFixed","left","innerText","formatTime","seconds","min","sec","floor","touchEnd","opt","direction","newPosition","console","msg","on","name","fnName","eventCallback","k","value","ec","remove","destroy"],"mappings":"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","file":"stvideo.min.js"}
--------------------------------------------------------------------------------
/src/js/stvideo.js:
--------------------------------------------------------------------------------
1 | /* global define */
2 |
3 | ( function( root, factory ) {
4 | if ( typeof define === 'function' && define.amd ) {
5 | define( [], function() {
6 | return factory( root );
7 | } );
8 | } else if ( typeof module === 'object' && module.exports ) {
9 | module.exports = factory( root );
10 | } else {
11 | root.stVideo = factory( root );
12 | }
13 | } )( typeof global !== 'undefined' ? global : this.window || this.global, function( root ) {
14 | 'use strict';
15 |
16 | ( function( window ) {
17 | var lastTime = 0;
18 | var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
19 |
20 | for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x ) {
21 | window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
22 | window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
23 | }
24 |
25 | if ( !window.requestAnimationFrame ) {
26 | window.requestAnimationFrame = function( callback, element ) {
27 | var currTime = new Date().getTime();
28 | var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
29 | var id = window.setTimeout( function() {
30 | callback( currTime + timeToCall );
31 | }, timeToCall );
32 | lastTime = currTime + timeToCall;
33 | return id;
34 | };
35 | }
36 |
37 | if ( !window.cancelAnimationFrame ) {
38 | window.cancelAnimationFrame = function( id ) {
39 | clearTimeout( id );
40 | };
41 | }
42 | }( root ) );
43 |
44 | var stVideo = function( el, settings ) {
45 | this.iOS = ( /iPhone|iPad|iPod/i.test( navigator.userAgent ) );
46 |
47 | this.iOSv = parseFloat( ( '' + ( /CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec( navigator.userAgent ) || [ 0, '' ] )[ 1 ] ).replace( '_', '.' ).replace( '_', '' ) ) || false;
48 |
49 | if ( this.iOS && this.iOSv < 10 ) {
50 | this.useCanvas = true;
51 | } else {
52 | this.useCanvas = false;
53 | }
54 |
55 | this.isMobile = navigator.userAgent.match( /Android|AvantGo|BlackBerry|DoCoMo|Fennec|iPod|iPhone|iPad|J2ME|MIDP|NetFront|Nokia|Opera Mini|Opera Mobi|PalmOS|PalmSource|portalmmm|Plucker|ReqwirelessWeb|SonyEricsson|Symbian|UP\\.Browser|webOS|Windows CE|Windows Phone OS|Xiino/i );
56 |
57 | this.useTouch = !!( 'ontouchstart' in window ) || !!( 'ontouchstart' in document.documentElement ) || !!window.ontouchstart || !!window.onmsgesturechange || ( window.DocumentTouch && window.document instanceof window.DocumentTouch );
58 |
59 | if ( typeof el === 'object' ) {
60 | this.element = el;
61 | } else {
62 | this.element = document.querySelector( el );
63 | }
64 |
65 | this.defaults = {
66 | force : '', // video | canvas
67 | framesPerSecond : 30,
68 | volume : 1
69 | };
70 |
71 | this.settings = this.getSettings( settings );
72 |
73 | if ( !( this.settings.mp4 || this.settings.webm || this.settings.ogg ) ||
74 | !this.settings.width || !this.settings.height ) {
75 |
76 | this.isError = true;
77 |
78 | this.error.checkSettings();
79 |
80 | return;
81 | }
82 |
83 | if ( this.settings.force === 'video' ) {
84 | this.useCanvas = false;
85 | } else if ( this.settings.force === 'canvas' ) {
86 | this.useCanvas = true;
87 | }
88 |
89 | this.classNames = {
90 | init : 'stvideo-box',
91 | error : 'stvideo-box--error',
92 | isPlaying : 'stvideo-box--is-playing',
93 | isPaused : 'stvideo-box--is-paused',
94 | isEnded : 'stvideo-box--is-ended',
95 | isMuted : 'stvideo-box--is-muted',
96 | isHandle : 'stvideo-box--is-handle',
97 | hasAudio : 'stvideo-box--has-audio',
98 | player : 'stvideo-box__player',
99 | poster : 'stvideo-box__poster',
100 | play : 'stvideo-box__play',
101 | playPause : 'stvideo-box__play-pause',
102 | controls : 'stvideo-box__controls',
103 | timeline : 'stvideo-box__timeline',
104 | progress : 'stvideo-box__progress',
105 | handle : 'stvideo-box__handle',
106 | duration : 'stvideo-box__duration',
107 | volume : 'stvideo-box__volume',
108 | };
109 |
110 | this.timelineSettings = {
111 | wrapperWidth : 0,
112 | isMouseDown : false,
113 | isHandleMoving : false,
114 | startX : 0,
115 | touchObj : null,
116 | posLeft : 0,
117 | lastPosLeft : 0,
118 | lastDistance : 0,
119 | lastDirection : ''
120 | };
121 |
122 | this.eventsUserCollection = [];
123 | this.eventsVideoCollection = [];
124 | this.eventsControlsCollection = [];
125 |
126 | this.initPlayer();
127 | };
128 |
129 | stVideo.prototype.getSettings = function( settings ) {
130 | var attr, options, key;
131 |
132 | if ( !settings ) {
133 | attr = this.element.getAttribute( 'data-stvideo' );
134 | attr = attr.replace( /\'/g, '"' );
135 | settings = JSON.parse( attr );
136 | }
137 |
138 | options = this.defaults;
139 |
140 | for ( key in settings ) {
141 | if ( settings.hasOwnProperty( key ) ) {
142 | options[ key ] = settings[ key ];
143 | }
144 | }
145 |
146 | return options;
147 | };
148 |
149 | stVideo.prototype.isContained = function( m, ev ) {
150 | var e = ev || window.event;
151 |
152 | var c = /(click)|(mousedown)|(mouseup)/i.test( e.type ) ? e.target : ( e.relatedTarget || ( ( e.type == 'mouseover' ) ? e.fromElement : e.toElement ) );
153 |
154 | while ( c && c != m ) {
155 | try {
156 | c = c.parentNode;
157 | } catch ( er ) {
158 | c = m;
159 | }
160 | }
161 |
162 | if ( c == m ) {
163 | return true;
164 | } else {
165 | return false;
166 | }
167 | };
168 |
169 | stVideo.prototype.initPlayer = function() {
170 | var self = this, format, wrapper, video, videoSource, type, canvas, canvasContext, itemIndex;
171 |
172 | this.element.classList.add( this.classNames.init );
173 |
174 | video = document.createElement( 'video' );
175 | video.setAttribute( 'width', this.settings.width );
176 | video.setAttribute( 'height', this.settings.height );
177 |
178 | if ( this.iOS && this.iOSv >= 10 ) {
179 | video.setAttribute( 'playsinline', '' );
180 | }
181 |
182 | format = this.supportedVideoFormat( video );
183 |
184 | if ( !format || ( this.useCanvas && !this.settings.mp4 ) || !this.settings[ format.ext ] ) {
185 | this.error.badVideoFormat.call( this );
186 |
187 | return;
188 | }
189 |
190 | videoSource = document.createElement( 'source' );
191 | videoSource.setAttribute( 'src', this.settings[ format.ext ] );
192 | videoSource.setAttribute( 'type', format.type );
193 |
194 | video.appendChild( videoSource );
195 |
196 | wrapper = document.createElement( 'div' );
197 | wrapper.classList.add( this.classNames.player );
198 |
199 | if ( this.useCanvas ) {
200 | canvas = document.createElement( 'canvas' );
201 | canvas.setAttribute( 'width', this.settings.width );
202 | canvas.setAttribute( 'height', this.settings.height );
203 |
204 | canvasContext = canvas.getContext( '2d' );
205 |
206 | canvasContext.fillStyle = '#ffffff';
207 | canvasContext.fillRect( 0, 0, this.settings.width, this.settings.height );
208 |
209 | canvasContext.drawImage( video, 0, 0, this.settings.width, this.settings.height );
210 |
211 | this.canvasContext = canvasContext;
212 |
213 | wrapper.appendChild( canvas );
214 | } else {
215 | wrapper.appendChild( video );
216 | }
217 |
218 | this.element.appendChild( wrapper );
219 |
220 | video.load();
221 |
222 | this.video = video;
223 |
224 | this.playerControls();
225 | this.addVideoListeners();
226 | this.addControlsListeners();
227 |
228 | if ( this.isMobile ) {
229 | window.addEventListener( 'orientationchange', function() {
230 | if ( this.resizeTo ) {
231 | clearTimeout( this.resizeTo );
232 | }
233 |
234 | this.resizeTo = setTimeout( function() {
235 | for ( itemIndex = 0; itemIndex < self.resizeCacheArr.length; itemIndex++ ) {
236 | self.resizeCacheArr[ itemIndex ]();
237 | }
238 | }, 200 );
239 | }, false );
240 | } else {
241 | window.addEventListener( 'resize', function() {
242 | if ( this.resizeTo ) {
243 | clearTimeout( this.resizeTo );
244 | }
245 |
246 | this.resizeTo = setTimeout( function() {
247 | for ( itemIndex = 0; itemIndex < self.resizeCacheArr.length; itemIndex++ ) {
248 | self.resizeCacheArr[ itemIndex ]();
249 | }
250 | }, 200 );
251 | } );
252 | }
253 | };
254 |
255 | stVideo.prototype.resizeHandler = function( fn ) {
256 | this.resizeCacheArr = this.resizeCacheArr || [];
257 |
258 | fn();
259 |
260 | this.resizeCacheArr.push( fn );
261 | };
262 |
263 | stVideo.prototype.supportedVideoFormat = function( video ) {
264 | var options = {};
265 |
266 | if ( video.canPlayType( 'video/webm' ) === 'probably' || video.canPlayType( 'video/webm' ) === 'maybe' ) {
267 | options.ext = 'webm';
268 | options.type = 'video/webm; codecs="vp8, vorbis"';
269 | } else if ( video.canPlayType( 'video/mp4' ) === 'probably' || video.canPlayType( 'video/mp4' ) === 'maybe' ) {
270 | options.ext = 'mp4';
271 | options.type = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
272 | } else if ( video.canPlayType( 'video/ogg' ) === 'probably' || video.canPlayType( 'video/ogg' ) === 'maybe' ) {
273 | options.ext = 'ogg';
274 | options.type = 'video/ogg; codecs="theora, vorbis"';
275 | }
276 |
277 | return options;
278 | };
279 |
280 | stVideo.prototype.videoAudio = function( video ) {
281 | var self = this, tempEvent, volume;
282 |
283 | if ( video.mozHasAudio || Boolean( video.webkitAudioDecodedByteCount ) || Boolean( video.audioTracks && video.audioTracks.length ) ) {
284 | this.hasAudio = true;
285 |
286 | this.element.classList.add( this.classNames.hasAudio );
287 |
288 | volume = document.createElement( 'div' );
289 | volume.classList.add( this.classNames.volume );
290 |
291 | this.elControls.appendChild( volume );
292 |
293 | this.elVolume = volume;
294 |
295 | this.elVolume.addEventListener( 'click', tempEvent = function() {
296 | if ( self.isMuted ) {
297 | self.video.volume = self.settings.volume;
298 |
299 | if ( self.audio ) {
300 | self.audio.volume = self.settings.volume;
301 |
302 | self.audio.currentTime = self.video.currentTime;
303 |
304 | if ( self.isPlaying ) {
305 | self.audio.play();
306 | }
307 |
308 | if ( self.iOS ) {
309 | self.changeState( 'muted', false );
310 | }
311 | }
312 | } else {
313 | self.video.volume = 0.01;
314 |
315 | if ( self.audio ) {
316 | self.audio.volume = 0.01; // hmm doesn't work on iPhone
317 | self.audio.pause();
318 |
319 | if ( self.iOS ) {
320 | self.changeState( 'muted', true );
321 | }
322 | }
323 | }
324 | } );
325 | this.eventsControlsCollection.push( tempEvent );
326 | } else {
327 | this.hasAudio = false;
328 | }
329 |
330 | return this.hasAudio;
331 | };
332 |
333 | stVideo.prototype.playerControls = function() {
334 | var self = this, poster, controls, timeline, progress, handle, playPause, play, duration;
335 |
336 | if ( this.settings.poster ) {
337 | poster = document.createElement( 'div' );
338 | poster.classList.add( this.classNames.poster );
339 | poster.style.backgroundImage = 'url(' + this.settings.poster + ')';
340 |
341 | this.element.appendChild( poster );
342 | }
343 |
344 | play = document.createElement( 'div' );
345 | play.classList.add( this.classNames.play );
346 |
347 | controls = document.createElement( 'div' );
348 | controls.classList.add( this.classNames.controls );
349 |
350 | playPause = document.createElement( 'div' );
351 | playPause.classList.add( this.classNames.playPause );
352 |
353 | timeline = document.createElement( 'div' );
354 | timeline.classList.add( this.classNames.timeline );
355 |
356 | progress = document.createElement( 'div' );
357 | progress.classList.add( this.classNames.progress );
358 |
359 | handle = document.createElement( 'div' );
360 | handle.classList.add( this.classNames.handle );
361 |
362 | duration = document.createElement( 'div' );
363 | duration.classList.add( this.classNames.duration );
364 |
365 | timeline.appendChild( progress );
366 | timeline.appendChild( handle );
367 | controls.appendChild( timeline );
368 | controls.appendChild( playPause );
369 | controls.appendChild( duration );
370 |
371 | this.element.appendChild( controls );
372 | this.element.appendChild( play );
373 |
374 | this.elControls = controls;
375 | this.elPlay = play;
376 | this.elPlayPause = playPause;
377 | this.elTimeline = timeline;
378 | this.elProgress = progress;
379 | this.elHandle = handle;
380 | this.elDuration = duration;
381 | };
382 |
383 | stVideo.prototype.addVideoListeners = function() {
384 | var self = this, tempEvent;
385 |
386 | this.video.addEventListener( 'loadedmetadata', tempEvent = function() {
387 | var audio = self.videoAudio( this );
388 |
389 | if ( self.useCanvas && audio ) {
390 | self.canvasAudio();
391 | }
392 | } );
393 | self.eventsVideoCollection.push( tempEvent );
394 |
395 | this.video.addEventListener( 'canplaythrough', tempEvent = function() {
396 | if ( self.useCanvas ) {
397 | self.canvasDrawFrame();
398 | }
399 |
400 | self.progressUpdate();
401 |
402 | setTimeout( function() {
403 | self.resizeHandler( function() {
404 | self.timelineSettings.wrapperWidth = self.elTimeline.offsetWidth;
405 | } );
406 | }, 100 );
407 | } );
408 | self.eventsVideoCollection.push( tempEvent );
409 |
410 | if ( !self.useCanvas ) {
411 | this.video.addEventListener( 'play', tempEvent = function() {
412 | self.changeState( 'play', true );
413 | self.changeState( 'end', false );
414 | } );
415 | self.eventsVideoCollection.push( tempEvent );
416 |
417 | this.video.addEventListener( 'pause', tempEvent = function() {
418 | self.changeState( 'pause', true );
419 | self.changeState( 'play', false );
420 | } );
421 | self.eventsVideoCollection.push( tempEvent );
422 |
423 | this.video.addEventListener( 'ended', tempEvent = function() {
424 | self.changeState( 'end', true );
425 | self.changeState( 'play', false );
426 | } );
427 | self.eventsVideoCollection.push( tempEvent );
428 | }
429 |
430 | this.video.addEventListener( 'timeupdate', tempEvent = function() {
431 | if ( self.useCanvas ) {
432 | self.canvasDrawFrame();
433 | }
434 |
435 | self.progressUpdate();
436 | } );
437 | self.eventsVideoCollection.push( tempEvent );
438 |
439 | this.video.addEventListener( 'volumechange', tempEvent = function() {
440 | if ( this.volume > 0.01 ) {
441 | self.changeState( 'muted', false );
442 | } else {
443 | self.changeState( 'muted', true );
444 | }
445 | } );
446 | self.eventsVideoCollection.push( tempEvent );
447 |
448 | this.video.addEventListener( 'error', tempEvent = function( ev ) {
449 | self.isError = true;
450 |
451 | self.error.custom( ev );
452 | } );
453 | self.eventsVideoCollection.push( tempEvent );
454 | };
455 |
456 | stVideo.prototype.addControlsListeners = function( controlsBox ) {
457 | var self = this, tempEvent;
458 |
459 | this.elPlay.addEventListener( 'click', tempEvent = function() {
460 | if ( !self.isPlaying ) {
461 | self.play();
462 | } else {
463 | self.pause();
464 | }
465 | } );
466 | self.eventsControlsCollection.push( tempEvent );
467 |
468 | this.elPlayPause.addEventListener( 'click', tempEvent = function() {
469 | if ( !self.isPlaying ) {
470 | self.play();
471 | } else {
472 | self.pause();
473 | }
474 | } );
475 | self.eventsControlsCollection.push( tempEvent );
476 |
477 | if ( !this.useTouch ) {
478 | document.body.addEventListener( 'mousedown', tempEvent = function( e ) {
479 | e.preventDefault();
480 |
481 | self.timelineSettings.isHandleMoving = true;
482 |
483 | if ( self.isContained( self.elHandle, e ) ) {
484 | self.timelineSettings.touchObj = e;
485 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
486 | self.timelineSettings.startX = parseInt( e.clientX );
487 |
488 | self.timelineSettings.isMouseDown = true;
489 |
490 | self.changeState( 'handle', true );
491 | } else if ( self.isContained( self.elTimeline, e ) ) {
492 | self.timelineSettings.touchObj = e;
493 | self.timelineSettings.posLeft = 0;
494 | self.timelineSettings.startX = parseInt( e.layerX );
495 |
496 | var dist = self.timelineSettings.startX;
497 |
498 | self.moveHandle( dist, true );
499 |
500 | self.timelineSettings.isHandleMoving = false;
501 | } else {
502 | self.timelineSettings.isHandleMoving = false;
503 | }
504 | }, false );
505 | self.eventsControlsCollection.push( tempEvent );
506 |
507 | document.body.addEventListener( 'mousemove', tempEvent = function( e ) {
508 | e.preventDefault();
509 |
510 | if ( self.timelineSettings.isMouseDown && self.timelineSettings.isHandleMoving ) {
511 | self.timelineSettings.touchObj = e;
512 |
513 | var dist = parseInt( self.timelineSettings.touchObj.clientX ) - self.timelineSettings.startX;
514 |
515 | self.moveHandle( dist );
516 | }
517 | }, false );
518 | self.eventsControlsCollection.push( tempEvent );
519 |
520 | document.body.addEventListener( 'mouseup', tempEvent = function( e ) {
521 | e.preventDefault();
522 |
523 | if ( self.timelineSettings.isMouseDown ) {
524 | self.timelineSettings.touchObj = e;
525 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
526 | self.timelineSettings.startX = parseInt( self.timelineSettings.touchObj.clientX );
527 |
528 | self.timelineSettings.isMouseDown = false;
529 |
530 | self.moveHandle( 0, true );
531 |
532 | self.changeState( 'handle', false );
533 |
534 | self.timelineSettings.isHandleMoving = false;
535 | }
536 | }, false );
537 | self.eventsControlsCollection.push( tempEvent );
538 |
539 | } else {
540 | this.elHandle.addEventListener( 'touchstart', tempEvent = function( e ) {
541 | // e.preventDefault();
542 | e.stopPropagation();
543 |
544 | self.timelineSettings.isHandleMoving = true;
545 |
546 | self.timelineSettings.touchObj = e.changedTouches[ 0 ];
547 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
548 | self.timelineSettings.startX = parseInt( self.timelineSettings.touchObj.clientX );
549 |
550 | self.changeState( 'handle', true );
551 | }, false );
552 | self.eventsControlsCollection.push( tempEvent );
553 |
554 | this.elHandle.addEventListener( 'touchmove', tempEvent = function( e ) {
555 |
556 | if ( self.timelineSettings.isHandleMoving ) {
557 | // e.preventDefault();
558 | e.stopPropagation();
559 |
560 | self.timelineSettings.touchObj = e.changedTouches[ 0 ];
561 |
562 | var dist = parseInt( self.timelineSettings.touchObj.clientX ) - self.timelineSettings.startX;
563 |
564 | self.moveHandle( dist );
565 | }
566 | }, false );
567 | self.eventsControlsCollection.push( tempEvent );
568 |
569 | this.elHandle.addEventListener( 'touchend', tempEvent = function( e ) {
570 | e.preventDefault();
571 |
572 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
573 |
574 | self.moveHandle( 0, true );
575 |
576 | self.changeState( 'handle', false );
577 |
578 | self.timelineSettings.isHandleMoving = false;
579 | }, false );
580 | self.eventsControlsCollection.push( tempEvent );
581 | }
582 | };
583 |
584 | stVideo.prototype.canvasAudio = function() {
585 | this.audio = document.createElement( 'audio' );
586 |
587 | this.audio.innerHTML = this.video.innerHTML;
588 |
589 | this.audio.load();
590 | };
591 |
592 | stVideo.prototype.canvasControl = function( action ) {
593 | if ( action === 'play' || ( action === 'play' && this.isEnded ) ) {
594 | if ( this.isEnded ) {
595 | this.changeState( 'end', false );
596 |
597 | this.video.currentTime = 0;
598 |
599 | if ( this.audio ) {
600 | this.audio.currentTime = 0;
601 | }
602 |
603 | this.lastTime = Date.now();
604 | }
605 |
606 | if ( this.audio && this.isMuted !== true ) {
607 | this.audio.play();
608 | }
609 |
610 | this.changeState( 'play', true );
611 |
612 | this.animationFrame = root.requestAnimationFrame( this.canvasFrameUpdate.bind( this ) );
613 |
614 | } else if ( action === 'pause' || action === 'ended' ) {
615 | if ( action === 'ended' ) {
616 | this.changeState( 'end', true );
617 | } else {
618 | this.changeState( 'pause', true );
619 | }
620 |
621 | if ( this.audio ) {
622 | this.audio.pause();
623 | }
624 |
625 | this.changeState( 'play', false );
626 |
627 | root.cancelAnimationFrame( this.animationFrame );
628 | }
629 | };
630 |
631 | stVideo.prototype.canvasFrameUpdate = function() {
632 | var time = Date.now(),
633 | elapsed = ( time - ( this.lastTime || time ) ) / 1000;
634 |
635 | if ( !elapsed || elapsed >= 1 / this.settings.framesPerSecond ) {
636 | this.video.currentTime = this.video.currentTime + elapsed;
637 |
638 | /* if(this.audio && Math.abs(this.audio.currentTime - this.video.currentTime) > 0.3){
639 | this.audio.pause();
640 | this.audio.currentTime = this.video.currentTime;
641 | this.audio.play();
642 | } */
643 |
644 | this.lastTime = time;
645 | }
646 |
647 | if ( this.video.currentTime >= this.video.duration ) {
648 | this.canvasControl( 'ended' );
649 | } else {
650 | this.animationFrame = root.requestAnimationFrame( this.canvasFrameUpdate.bind( this ) );
651 | }
652 | };
653 |
654 | stVideo.prototype.canvasDrawFrame = function() {
655 | this.canvasContext.drawImage( this.video, 0, 0, this.settings.width, this.settings.height );
656 | };
657 |
658 | stVideo.prototype.progressUpdate = function( movedByDistance ) {
659 | var current = this.video.currentTime,
660 | duration = this.video.duration,
661 | timeline = this.timelineSettings;
662 |
663 | if ( movedByDistance ) {
664 | current = this.video.currentTime = ( movedByDistance / timeline.wrapperWidth ) * duration;
665 | }
666 |
667 | var progress = ( current / duration * timeline.wrapperWidth ).toFixed( 2 );
668 |
669 | if ( progress < 0 ) {
670 | progress = 0;
671 | } else if ( progress > timeline.wrapperWidth ) {
672 | progress = timeline.wrapperWidth;
673 | }
674 |
675 | this.elProgress.style.width = +progress + 'px';
676 |
677 | if ( !timeline.isHandleMoving ) {
678 | this.elHandle.style.left = +progress + 'px';
679 | }
680 |
681 | this.elDuration.innerText = this.formatTime( current ) + ' / ' + this.formatTime( duration );
682 | };
683 |
684 | stVideo.prototype.formatTime = function( seconds ) {
685 | var min, sec;
686 |
687 | min = Math.floor( seconds / 60 );
688 | min = ( min >= 10 ) ? min : '0' + min;
689 | sec = Math.floor( seconds % 60 );
690 | sec = ( sec >= 10 ) ? sec : '0' + sec;
691 |
692 | return min + ':' + sec;
693 | };
694 |
695 | stVideo.prototype.moveHandle = function( movedByDistance, touchEnd ) {
696 | var opt = this.timelineSettings;
697 |
698 | if ( !opt.isHandleMoving ) {
699 | return;
700 | }
701 |
702 | var direction = ( ( touchEnd ? opt.lastDistance : movedByDistance ) > 0 ) ? 'right' : 'left';
703 |
704 | var newPosition = opt.posLeft + movedByDistance;
705 |
706 | if ( newPosition < 0 ) {
707 | newPosition = 0;
708 | } else if ( newPosition > opt.wrapperWidth ) {
709 | newPosition = opt.wrapperWidth;
710 | }
711 |
712 | this.elHandle.style.left = newPosition + 'px';
713 |
714 | opt.lastPosLeft = newPosition;
715 | opt.lastDistance = movedByDistance;
716 | opt.lastDirection = direction;
717 |
718 | if ( touchEnd ) {
719 | this.progressUpdate( newPosition );
720 | }
721 | };
722 |
723 | stVideo.prototype.error = {
724 | badVideoFormat: function() {
725 | if ( this.useCanvas ) {
726 | console.error( 'Apple devices support only .mp4 format' );
727 | } else {
728 | console.error( 'Best use .webm and .mp4 video formats' );
729 | }
730 |
731 | this.element.classList.add( this.classNames.error );
732 | },
733 | checkSettings: function() {
734 | console.error( 'Check all required settings' );
735 |
736 | this.element.classList.add( this.classNames.error );
737 | },
738 | custom: function( msg ) {
739 | console.error( msg );
740 |
741 | this.element.classList.add( this.classNames.error );
742 | }
743 | };
744 |
745 | stVideo.prototype.on = function( name, callback ) {
746 | if ( this.isError ) {
747 | return;
748 | }
749 |
750 | var self = this, tempEvent;
751 |
752 | // this.allowedEvents = ['canplay', 'canplaythrough', 'play', 'playing', 'pause', 'ended', 'abort', 'error', 'timeupdate'];
753 |
754 | // if(this.allowedEvents.indexOf(name) == -1) return;
755 |
756 | this.video.addEventListener( name, tempEvent = function() {
757 | callback.call( this );
758 | } );
759 |
760 | tempEvent.fnName = name;
761 |
762 | self.eventsUserCollection.push( tempEvent );
763 | };
764 |
765 | stVideo.prototype.eventCallback = function( name ) {
766 | if ( this.useCanvas ) {
767 | for ( var k in this.eventsUserCollection ) {
768 | if ( this.eventsUserCollection[ k ].fnName === name ) {
769 | this.eventsUserCollection[ k ]();
770 | }
771 | }
772 | }
773 | };
774 |
775 | stVideo.prototype.play = function() {
776 | if ( this.isError ) {
777 | return;
778 | }
779 |
780 | this.lastTime = Date.now();
781 |
782 | if ( this.useCanvas ) {
783 | this.canvasControl( 'play' );
784 | } else {
785 | this.video.play();
786 | }
787 | };
788 |
789 | stVideo.prototype.pause = function() {
790 | if ( this.isError ) {
791 | return;
792 | }
793 |
794 | if ( this.isPlaying ) {
795 | if ( this.useCanvas ) {
796 | this.canvasControl( 'pause' );
797 | } else {
798 | this.video.pause();
799 | }
800 | }
801 | };
802 |
803 | stVideo.prototype.changeState = function( action, value ) {
804 | var ec = this.element.classList;
805 |
806 | if ( action === 'play' ) {
807 | this.isPlaying = value;
808 |
809 | if ( value ) {
810 | ec.add( this.classNames.isPlaying );
811 |
812 | this.eventCallback( 'play' );
813 | } else {
814 | ec.remove( this.classNames.isPlaying );
815 | }
816 | }
817 |
818 | if ( action === 'pause' ) {
819 | this.isPaused = value;
820 |
821 | if ( value ) {
822 | ec.add( this.classNames.isPaused );
823 |
824 | this.eventCallback( 'pause' );
825 | } else {
826 | ec.remove( this.classNames.isPaused );
827 | }
828 | }
829 |
830 | if ( action === 'end' ) {
831 | this.isEnded = value;
832 |
833 | if ( value ) {
834 | ec.add( this.classNames.isEnded );
835 |
836 | this.eventCallback( 'end' );
837 | } else {
838 | ec.remove( this.classNames.isEnded );
839 | }
840 | }
841 |
842 | if ( action === 'muted' ) {
843 | this.isMuted = value;
844 |
845 | if ( value ) {
846 | ec.add( this.classNames.isMuted );
847 |
848 | this.eventCallback( 'muted' );
849 | } else {
850 | ec.remove( this.classNames.isMuted );
851 | }
852 | }
853 |
854 | if ( action === 'handle' ) {
855 | this.isMuted = value;
856 |
857 | if ( value ) {
858 | ec.add( this.classNames.isHandle );
859 | } else {
860 | ec.remove( this.classNames.isHandle );
861 | }
862 | }
863 | };
864 |
865 | stVideo.prototype.destroy = function() {
866 |
867 | };
868 |
869 | return stVideo;
870 | } );
871 |
--------------------------------------------------------------------------------
/dist/js/stvideo.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * stVideo
3 | * HTML5 video canvas player. Prevents video fullscreen on iPhone/iPad.
4 | *
5 | * Licensed under the MIT license:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Any and all use of this script must be accompanied by this copyright/license notice in its present form.
9 | *
10 | * Version: 0.9.0
11 | * Author: Tomasz Stabla (http://stabla.com)
12 | * Site: https://github.com/tstabla/stVideo/
13 | */
14 | /* global define */
15 |
16 | ( function( root, factory ) {
17 | if ( typeof define === 'function' && define.amd ) {
18 | define( [], function() {
19 | return factory( root );
20 | } );
21 | } else if ( typeof module === 'object' && module.exports ) {
22 | module.exports = factory( root );
23 | } else {
24 | root.stVideo = factory( root );
25 | }
26 | } )( typeof global !== 'undefined' ? global : this.window || this.global, function( root ) {
27 | 'use strict';
28 |
29 | ( function( window ) {
30 | var lastTime = 0;
31 | var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
32 |
33 | for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x ) {
34 | window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
35 | window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
36 | }
37 |
38 | if ( !window.requestAnimationFrame ) {
39 | window.requestAnimationFrame = function( callback, element ) {
40 | var currTime = new Date().getTime();
41 | var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
42 | var id = window.setTimeout( function() {
43 | callback( currTime + timeToCall );
44 | }, timeToCall );
45 | lastTime = currTime + timeToCall;
46 | return id;
47 | };
48 | }
49 |
50 | if ( !window.cancelAnimationFrame ) {
51 | window.cancelAnimationFrame = function( id ) {
52 | clearTimeout( id );
53 | };
54 | }
55 | }( root ) );
56 |
57 | var stVideo = function( el, settings ) {
58 | this.iOS = ( /iPhone|iPad|iPod/i.test( navigator.userAgent ) );
59 |
60 | this.iOSv = parseFloat( ( '' + ( /CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec( navigator.userAgent ) || [ 0, '' ] )[ 1 ] ).replace( '_', '.' ).replace( '_', '' ) ) || false;
61 |
62 | if ( this.iOS && this.iOSv < 10 ) {
63 | this.useCanvas = true;
64 | } else {
65 | this.useCanvas = false;
66 | }
67 |
68 | this.isMobile = navigator.userAgent.match( /Android|AvantGo|BlackBerry|DoCoMo|Fennec|iPod|iPhone|iPad|J2ME|MIDP|NetFront|Nokia|Opera Mini|Opera Mobi|PalmOS|PalmSource|portalmmm|Plucker|ReqwirelessWeb|SonyEricsson|Symbian|UP\\.Browser|webOS|Windows CE|Windows Phone OS|Xiino/i );
69 |
70 | this.useTouch = !!( 'ontouchstart' in window ) || !!( 'ontouchstart' in document.documentElement ) || !!window.ontouchstart || !!window.onmsgesturechange || ( window.DocumentTouch && window.document instanceof window.DocumentTouch );
71 |
72 | if ( typeof el === 'object' ) {
73 | this.element = el;
74 | } else {
75 | this.element = document.querySelector( el );
76 | }
77 |
78 | this.defaults = {
79 | force : '', // video | canvas
80 | framesPerSecond : 30,
81 | volume : 1
82 | };
83 |
84 | this.settings = this.getSettings( settings );
85 |
86 | if ( !( this.settings.mp4 || this.settings.webm || this.settings.ogg ) ||
87 | !this.settings.width || !this.settings.height ) {
88 |
89 | this.isError = true;
90 |
91 | this.error.checkSettings();
92 |
93 | return;
94 | }
95 |
96 | if ( this.settings.force === 'video' ) {
97 | this.useCanvas = false;
98 | } else if ( this.settings.force === 'canvas' ) {
99 | this.useCanvas = true;
100 | }
101 |
102 | this.classNames = {
103 | init : 'stvideo-box',
104 | error : 'stvideo-box--error',
105 | isPlaying : 'stvideo-box--is-playing',
106 | isPaused : 'stvideo-box--is-paused',
107 | isEnded : 'stvideo-box--is-ended',
108 | isMuted : 'stvideo-box--is-muted',
109 | isHandle : 'stvideo-box--is-handle',
110 | hasAudio : 'stvideo-box--has-audio',
111 | player : 'stvideo-box__player',
112 | poster : 'stvideo-box__poster',
113 | play : 'stvideo-box__play',
114 | playPause : 'stvideo-box__play-pause',
115 | controls : 'stvideo-box__controls',
116 | timeline : 'stvideo-box__timeline',
117 | progress : 'stvideo-box__progress',
118 | handle : 'stvideo-box__handle',
119 | duration : 'stvideo-box__duration',
120 | volume : 'stvideo-box__volume',
121 | };
122 |
123 | this.timelineSettings = {
124 | wrapperWidth : 0,
125 | isMouseDown : false,
126 | isHandleMoving : false,
127 | startX : 0,
128 | touchObj : null,
129 | posLeft : 0,
130 | lastPosLeft : 0,
131 | lastDistance : 0,
132 | lastDirection : ''
133 | };
134 |
135 | this.eventsUserCollection = [];
136 | this.eventsVideoCollection = [];
137 | this.eventsControlsCollection = [];
138 |
139 | this.initPlayer();
140 | };
141 |
142 | stVideo.prototype.getSettings = function( settings ) {
143 | var attr, options, key;
144 |
145 | if ( !settings ) {
146 | attr = this.element.getAttribute( 'data-stvideo' );
147 | attr = attr.replace( /\'/g, '"' );
148 | settings = JSON.parse( attr );
149 | }
150 |
151 | options = this.defaults;
152 |
153 | for ( key in settings ) {
154 | if ( settings.hasOwnProperty( key ) ) {
155 | options[ key ] = settings[ key ];
156 | }
157 | }
158 |
159 | return options;
160 | };
161 |
162 | stVideo.prototype.isContained = function( m, ev ) {
163 | var e = ev || window.event;
164 |
165 | var c = /(click)|(mousedown)|(mouseup)/i.test( e.type ) ? e.target : ( e.relatedTarget || ( ( e.type == 'mouseover' ) ? e.fromElement : e.toElement ) );
166 |
167 | while ( c && c != m ) {
168 | try {
169 | c = c.parentNode;
170 | } catch ( er ) {
171 | c = m;
172 | }
173 | }
174 |
175 | if ( c == m ) {
176 | return true;
177 | } else {
178 | return false;
179 | }
180 | };
181 |
182 | stVideo.prototype.initPlayer = function() {
183 | var self = this, format, wrapper, video, videoSource, type, canvas, canvasContext, itemIndex;
184 |
185 | this.element.classList.add( this.classNames.init );
186 |
187 | video = document.createElement( 'video' );
188 | video.setAttribute( 'width', this.settings.width );
189 | video.setAttribute( 'height', this.settings.height );
190 |
191 | if ( this.iOS && this.iOSv >= 10 ) {
192 | video.setAttribute( 'playsinline', '' );
193 | }
194 |
195 | format = this.supportedVideoFormat( video );
196 |
197 | if ( !format || ( this.useCanvas && !this.settings.mp4 ) || !this.settings[ format.ext ] ) {
198 | this.error.badVideoFormat.call( this );
199 |
200 | return;
201 | }
202 |
203 | videoSource = document.createElement( 'source' );
204 | videoSource.setAttribute( 'src', this.settings[ format.ext ] );
205 | videoSource.setAttribute( 'type', format.type );
206 |
207 | video.appendChild( videoSource );
208 |
209 | wrapper = document.createElement( 'div' );
210 | wrapper.classList.add( this.classNames.player );
211 |
212 | if ( this.useCanvas ) {
213 | canvas = document.createElement( 'canvas' );
214 | canvas.setAttribute( 'width', this.settings.width );
215 | canvas.setAttribute( 'height', this.settings.height );
216 |
217 | canvasContext = canvas.getContext( '2d' );
218 |
219 | canvasContext.fillStyle = '#ffffff';
220 | canvasContext.fillRect( 0, 0, this.settings.width, this.settings.height );
221 |
222 | canvasContext.drawImage( video, 0, 0, this.settings.width, this.settings.height );
223 |
224 | this.canvasContext = canvasContext;
225 |
226 | wrapper.appendChild( canvas );
227 | } else {
228 | wrapper.appendChild( video );
229 | }
230 |
231 | this.element.appendChild( wrapper );
232 |
233 | video.load();
234 |
235 | this.video = video;
236 |
237 | this.playerControls();
238 | this.addVideoListeners();
239 | this.addControlsListeners();
240 |
241 | if ( this.isMobile ) {
242 | window.addEventListener( 'orientationchange', function() {
243 | if ( this.resizeTo ) {
244 | clearTimeout( this.resizeTo );
245 | }
246 |
247 | this.resizeTo = setTimeout( function() {
248 | for ( itemIndex = 0; itemIndex < self.resizeCacheArr.length; itemIndex++ ) {
249 | self.resizeCacheArr[ itemIndex ]();
250 | }
251 | }, 200 );
252 | }, false );
253 | } else {
254 | window.addEventListener( 'resize', function() {
255 | if ( this.resizeTo ) {
256 | clearTimeout( this.resizeTo );
257 | }
258 |
259 | this.resizeTo = setTimeout( function() {
260 | for ( itemIndex = 0; itemIndex < self.resizeCacheArr.length; itemIndex++ ) {
261 | self.resizeCacheArr[ itemIndex ]();
262 | }
263 | }, 200 );
264 | } );
265 | }
266 | };
267 |
268 | stVideo.prototype.resizeHandler = function( fn ) {
269 | this.resizeCacheArr = this.resizeCacheArr || [];
270 |
271 | fn();
272 |
273 | this.resizeCacheArr.push( fn );
274 | };
275 |
276 | stVideo.prototype.supportedVideoFormat = function( video ) {
277 | var options = {};
278 |
279 | if ( video.canPlayType( 'video/webm' ) === 'probably' || video.canPlayType( 'video/webm' ) === 'maybe' ) {
280 | options.ext = 'webm';
281 | options.type = 'video/webm; codecs="vp8, vorbis"';
282 | } else if ( video.canPlayType( 'video/mp4' ) === 'probably' || video.canPlayType( 'video/mp4' ) === 'maybe' ) {
283 | options.ext = 'mp4';
284 | options.type = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
285 | } else if ( video.canPlayType( 'video/ogg' ) === 'probably' || video.canPlayType( 'video/ogg' ) === 'maybe' ) {
286 | options.ext = 'ogg';
287 | options.type = 'video/ogg; codecs="theora, vorbis"';
288 | }
289 |
290 | return options;
291 | };
292 |
293 | stVideo.prototype.videoAudio = function( video ) {
294 | var self = this, tempEvent, volume;
295 |
296 | if ( video.mozHasAudio || Boolean( video.webkitAudioDecodedByteCount ) || Boolean( video.audioTracks && video.audioTracks.length ) ) {
297 | this.hasAudio = true;
298 |
299 | this.element.classList.add( this.classNames.hasAudio );
300 |
301 | volume = document.createElement( 'div' );
302 | volume.classList.add( this.classNames.volume );
303 |
304 | this.elControls.appendChild( volume );
305 |
306 | this.elVolume = volume;
307 |
308 | this.elVolume.addEventListener( 'click', tempEvent = function() {
309 | if ( self.isMuted ) {
310 | self.video.volume = self.settings.volume;
311 |
312 | if ( self.audio ) {
313 | self.audio.volume = self.settings.volume;
314 |
315 | self.audio.currentTime = self.video.currentTime;
316 |
317 | if ( self.isPlaying ) {
318 | self.audio.play();
319 | }
320 |
321 | if ( self.iOS ) {
322 | self.changeState( 'muted', false );
323 | }
324 | }
325 | } else {
326 | self.video.volume = 0.01;
327 |
328 | if ( self.audio ) {
329 | self.audio.volume = 0.01; // hmm doesn't work on iPhone
330 | self.audio.pause();
331 |
332 | if ( self.iOS ) {
333 | self.changeState( 'muted', true );
334 | }
335 | }
336 | }
337 | } );
338 | this.eventsControlsCollection.push( tempEvent );
339 | } else {
340 | this.hasAudio = false;
341 | }
342 |
343 | return this.hasAudio;
344 | };
345 |
346 | stVideo.prototype.playerControls = function() {
347 | var self = this, poster, controls, timeline, progress, handle, playPause, play, duration;
348 |
349 | if ( this.settings.poster ) {
350 | poster = document.createElement( 'div' );
351 | poster.classList.add( this.classNames.poster );
352 | poster.style.backgroundImage = 'url(' + this.settings.poster + ')';
353 |
354 | this.element.appendChild( poster );
355 | }
356 |
357 | play = document.createElement( 'div' );
358 | play.classList.add( this.classNames.play );
359 |
360 | controls = document.createElement( 'div' );
361 | controls.classList.add( this.classNames.controls );
362 |
363 | playPause = document.createElement( 'div' );
364 | playPause.classList.add( this.classNames.playPause );
365 |
366 | timeline = document.createElement( 'div' );
367 | timeline.classList.add( this.classNames.timeline );
368 |
369 | progress = document.createElement( 'div' );
370 | progress.classList.add( this.classNames.progress );
371 |
372 | handle = document.createElement( 'div' );
373 | handle.classList.add( this.classNames.handle );
374 |
375 | duration = document.createElement( 'div' );
376 | duration.classList.add( this.classNames.duration );
377 |
378 | timeline.appendChild( progress );
379 | timeline.appendChild( handle );
380 | controls.appendChild( timeline );
381 | controls.appendChild( playPause );
382 | controls.appendChild( duration );
383 |
384 | this.element.appendChild( controls );
385 | this.element.appendChild( play );
386 |
387 | this.elControls = controls;
388 | this.elPlay = play;
389 | this.elPlayPause = playPause;
390 | this.elTimeline = timeline;
391 | this.elProgress = progress;
392 | this.elHandle = handle;
393 | this.elDuration = duration;
394 | };
395 |
396 | stVideo.prototype.addVideoListeners = function() {
397 | var self = this, tempEvent;
398 |
399 | this.video.addEventListener( 'loadedmetadata', tempEvent = function() {
400 | var audio = self.videoAudio( this );
401 |
402 | if ( self.useCanvas && audio ) {
403 | self.canvasAudio();
404 | }
405 | } );
406 | self.eventsVideoCollection.push( tempEvent );
407 |
408 | this.video.addEventListener( 'canplaythrough', tempEvent = function() {
409 | if ( self.useCanvas ) {
410 | self.canvasDrawFrame();
411 | }
412 |
413 | self.progressUpdate();
414 |
415 | setTimeout( function() {
416 | self.resizeHandler( function() {
417 | self.timelineSettings.wrapperWidth = self.elTimeline.offsetWidth;
418 | } );
419 | }, 100 );
420 | } );
421 | self.eventsVideoCollection.push( tempEvent );
422 |
423 | if ( !self.useCanvas ) {
424 | this.video.addEventListener( 'play', tempEvent = function() {
425 | self.changeState( 'play', true );
426 | self.changeState( 'end', false );
427 | } );
428 | self.eventsVideoCollection.push( tempEvent );
429 |
430 | this.video.addEventListener( 'pause', tempEvent = function() {
431 | self.changeState( 'pause', true );
432 | self.changeState( 'play', false );
433 | } );
434 | self.eventsVideoCollection.push( tempEvent );
435 |
436 | this.video.addEventListener( 'ended', tempEvent = function() {
437 | self.changeState( 'end', true );
438 | self.changeState( 'play', false );
439 | } );
440 | self.eventsVideoCollection.push( tempEvent );
441 | }
442 |
443 | this.video.addEventListener( 'timeupdate', tempEvent = function() {
444 | if ( self.useCanvas ) {
445 | self.canvasDrawFrame();
446 | }
447 |
448 | self.progressUpdate();
449 | } );
450 | self.eventsVideoCollection.push( tempEvent );
451 |
452 | this.video.addEventListener( 'volumechange', tempEvent = function() {
453 | if ( this.volume > 0.01 ) {
454 | self.changeState( 'muted', false );
455 | } else {
456 | self.changeState( 'muted', true );
457 | }
458 | } );
459 | self.eventsVideoCollection.push( tempEvent );
460 |
461 | this.video.addEventListener( 'error', tempEvent = function( ev ) {
462 | self.isError = true;
463 |
464 | self.error.custom( ev );
465 | } );
466 | self.eventsVideoCollection.push( tempEvent );
467 | };
468 |
469 | stVideo.prototype.addControlsListeners = function( controlsBox ) {
470 | var self = this, tempEvent;
471 |
472 | this.elPlay.addEventListener( 'click', tempEvent = function() {
473 | if ( !self.isPlaying ) {
474 | self.play();
475 | } else {
476 | self.pause();
477 | }
478 | } );
479 | self.eventsControlsCollection.push( tempEvent );
480 |
481 | this.elPlayPause.addEventListener( 'click', tempEvent = function() {
482 | if ( !self.isPlaying ) {
483 | self.play();
484 | } else {
485 | self.pause();
486 | }
487 | } );
488 | self.eventsControlsCollection.push( tempEvent );
489 |
490 | if ( !this.useTouch ) {
491 | document.body.addEventListener( 'mousedown', tempEvent = function( e ) {
492 | e.preventDefault();
493 |
494 | self.timelineSettings.isHandleMoving = true;
495 |
496 | if ( self.isContained( self.elHandle, e ) ) {
497 | self.timelineSettings.touchObj = e;
498 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
499 | self.timelineSettings.startX = parseInt( e.clientX );
500 |
501 | self.timelineSettings.isMouseDown = true;
502 |
503 | self.changeState( 'handle', true );
504 | } else if ( self.isContained( self.elTimeline, e ) ) {
505 | self.timelineSettings.touchObj = e;
506 | self.timelineSettings.posLeft = 0;
507 | self.timelineSettings.startX = parseInt( e.layerX );
508 |
509 | var dist = self.timelineSettings.startX;
510 |
511 | self.moveHandle( dist, true );
512 |
513 | self.timelineSettings.isHandleMoving = false;
514 | } else {
515 | self.timelineSettings.isHandleMoving = false;
516 | }
517 | }, false );
518 | self.eventsControlsCollection.push( tempEvent );
519 |
520 | document.body.addEventListener( 'mousemove', tempEvent = function( e ) {
521 | e.preventDefault();
522 |
523 | if ( self.timelineSettings.isMouseDown && self.timelineSettings.isHandleMoving ) {
524 | self.timelineSettings.touchObj = e;
525 |
526 | var dist = parseInt( self.timelineSettings.touchObj.clientX ) - self.timelineSettings.startX;
527 |
528 | self.moveHandle( dist );
529 | }
530 | }, false );
531 | self.eventsControlsCollection.push( tempEvent );
532 |
533 | document.body.addEventListener( 'mouseup', tempEvent = function( e ) {
534 | e.preventDefault();
535 |
536 | if ( self.timelineSettings.isMouseDown ) {
537 | self.timelineSettings.touchObj = e;
538 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
539 | self.timelineSettings.startX = parseInt( self.timelineSettings.touchObj.clientX );
540 |
541 | self.timelineSettings.isMouseDown = false;
542 |
543 | self.moveHandle( 0, true );
544 |
545 | self.changeState( 'handle', false );
546 |
547 | self.timelineSettings.isHandleMoving = false;
548 | }
549 | }, false );
550 | self.eventsControlsCollection.push( tempEvent );
551 |
552 | } else {
553 | this.elHandle.addEventListener( 'touchstart', tempEvent = function( e ) {
554 | // e.preventDefault();
555 | e.stopPropagation();
556 |
557 | self.timelineSettings.isHandleMoving = true;
558 |
559 | self.timelineSettings.touchObj = e.changedTouches[ 0 ];
560 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
561 | self.timelineSettings.startX = parseInt( self.timelineSettings.touchObj.clientX );
562 |
563 | self.changeState( 'handle', true );
564 | }, false );
565 | self.eventsControlsCollection.push( tempEvent );
566 |
567 | this.elHandle.addEventListener( 'touchmove', tempEvent = function( e ) {
568 |
569 | if ( self.timelineSettings.isHandleMoving ) {
570 | // e.preventDefault();
571 | e.stopPropagation();
572 |
573 | self.timelineSettings.touchObj = e.changedTouches[ 0 ];
574 |
575 | var dist = parseInt( self.timelineSettings.touchObj.clientX ) - self.timelineSettings.startX;
576 |
577 | self.moveHandle( dist );
578 | }
579 | }, false );
580 | self.eventsControlsCollection.push( tempEvent );
581 |
582 | this.elHandle.addEventListener( 'touchend', tempEvent = function( e ) {
583 | e.preventDefault();
584 |
585 | self.timelineSettings.posLeft = self.timelineSettings.lastPosLeft;
586 |
587 | self.moveHandle( 0, true );
588 |
589 | self.changeState( 'handle', false );
590 |
591 | self.timelineSettings.isHandleMoving = false;
592 | }, false );
593 | self.eventsControlsCollection.push( tempEvent );
594 | }
595 | };
596 |
597 | stVideo.prototype.canvasAudio = function() {
598 | this.audio = document.createElement( 'audio' );
599 |
600 | this.audio.innerHTML = this.video.innerHTML;
601 |
602 | this.audio.load();
603 | };
604 |
605 | stVideo.prototype.canvasControl = function( action ) {
606 | if ( action === 'play' || ( action === 'play' && this.isEnded ) ) {
607 | if ( this.isEnded ) {
608 | this.changeState( 'end', false );
609 |
610 | this.video.currentTime = 0;
611 |
612 | if ( this.audio ) {
613 | this.audio.currentTime = 0;
614 | }
615 |
616 | this.lastTime = Date.now();
617 | }
618 |
619 | if ( this.audio && this.isMuted !== true ) {
620 | this.audio.play();
621 | }
622 |
623 | this.changeState( 'play', true );
624 |
625 | this.animationFrame = root.requestAnimationFrame( this.canvasFrameUpdate.bind( this ) );
626 |
627 | } else if ( action === 'pause' || action === 'ended' ) {
628 | if ( action === 'ended' ) {
629 | this.changeState( 'end', true );
630 | } else {
631 | this.changeState( 'pause', true );
632 | }
633 |
634 | if ( this.audio ) {
635 | this.audio.pause();
636 | }
637 |
638 | this.changeState( 'play', false );
639 |
640 | root.cancelAnimationFrame( this.animationFrame );
641 | }
642 | };
643 |
644 | stVideo.prototype.canvasFrameUpdate = function() {
645 | var time = Date.now(),
646 | elapsed = ( time - ( this.lastTime || time ) ) / 1000;
647 |
648 | if ( !elapsed || elapsed >= 1 / this.settings.framesPerSecond ) {
649 | this.video.currentTime = this.video.currentTime + elapsed;
650 |
651 | /* if(this.audio && Math.abs(this.audio.currentTime - this.video.currentTime) > 0.3){
652 | this.audio.pause();
653 | this.audio.currentTime = this.video.currentTime;
654 | this.audio.play();
655 | } */
656 |
657 | this.lastTime = time;
658 | }
659 |
660 | if ( this.video.currentTime >= this.video.duration ) {
661 | this.canvasControl( 'ended' );
662 | } else {
663 | this.animationFrame = root.requestAnimationFrame( this.canvasFrameUpdate.bind( this ) );
664 | }
665 | };
666 |
667 | stVideo.prototype.canvasDrawFrame = function() {
668 | this.canvasContext.drawImage( this.video, 0, 0, this.settings.width, this.settings.height );
669 | };
670 |
671 | stVideo.prototype.progressUpdate = function( movedByDistance ) {
672 | var current = this.video.currentTime,
673 | duration = this.video.duration,
674 | timeline = this.timelineSettings;
675 |
676 | if ( movedByDistance ) {
677 | current = this.video.currentTime = ( movedByDistance / timeline.wrapperWidth ) * duration;
678 | }
679 |
680 | var progress = ( current / duration * timeline.wrapperWidth ).toFixed( 2 );
681 |
682 | if ( progress < 0 ) {
683 | progress = 0;
684 | } else if ( progress > timeline.wrapperWidth ) {
685 | progress = timeline.wrapperWidth;
686 | }
687 |
688 | this.elProgress.style.width = +progress + 'px';
689 |
690 | if ( !timeline.isHandleMoving ) {
691 | this.elHandle.style.left = +progress + 'px';
692 | }
693 |
694 | this.elDuration.innerText = this.formatTime( current ) + ' / ' + this.formatTime( duration );
695 | };
696 |
697 | stVideo.prototype.formatTime = function( seconds ) {
698 | var min, sec;
699 |
700 | min = Math.floor( seconds / 60 );
701 | min = ( min >= 10 ) ? min : '0' + min;
702 | sec = Math.floor( seconds % 60 );
703 | sec = ( sec >= 10 ) ? sec : '0' + sec;
704 |
705 | return min + ':' + sec;
706 | };
707 |
708 | stVideo.prototype.moveHandle = function( movedByDistance, touchEnd ) {
709 | var opt = this.timelineSettings;
710 |
711 | if ( !opt.isHandleMoving ) {
712 | return;
713 | }
714 |
715 | var direction = ( ( touchEnd ? opt.lastDistance : movedByDistance ) > 0 ) ? 'right' : 'left';
716 |
717 | var newPosition = opt.posLeft + movedByDistance;
718 |
719 | if ( newPosition < 0 ) {
720 | newPosition = 0;
721 | } else if ( newPosition > opt.wrapperWidth ) {
722 | newPosition = opt.wrapperWidth;
723 | }
724 |
725 | this.elHandle.style.left = newPosition + 'px';
726 |
727 | opt.lastPosLeft = newPosition;
728 | opt.lastDistance = movedByDistance;
729 | opt.lastDirection = direction;
730 |
731 | if ( touchEnd ) {
732 | this.progressUpdate( newPosition );
733 | }
734 | };
735 |
736 | stVideo.prototype.error = {
737 | badVideoFormat: function() {
738 | if ( this.useCanvas ) {
739 | console.error( 'Apple devices support only .mp4 format' );
740 | } else {
741 | console.error( 'Best use .webm and .mp4 video formats' );
742 | }
743 |
744 | this.element.classList.add( this.classNames.error );
745 | },
746 | checkSettings: function() {
747 | console.error( 'Check all required settings' );
748 |
749 | this.element.classList.add( this.classNames.error );
750 | },
751 | custom: function( msg ) {
752 | console.error( msg );
753 |
754 | this.element.classList.add( this.classNames.error );
755 | }
756 | };
757 |
758 | stVideo.prototype.on = function( name, callback ) {
759 | if ( this.isError ) {
760 | return;
761 | }
762 |
763 | var self = this, tempEvent;
764 |
765 | // this.allowedEvents = ['canplay', 'canplaythrough', 'play', 'playing', 'pause', 'ended', 'abort', 'error', 'timeupdate'];
766 |
767 | // if(this.allowedEvents.indexOf(name) == -1) return;
768 |
769 | this.video.addEventListener( name, tempEvent = function() {
770 | callback.call( this );
771 | } );
772 |
773 | tempEvent.fnName = name;
774 |
775 | self.eventsUserCollection.push( tempEvent );
776 | };
777 |
778 | stVideo.prototype.eventCallback = function( name ) {
779 | if ( this.useCanvas ) {
780 | for ( var k in this.eventsUserCollection ) {
781 | if ( this.eventsUserCollection[ k ].fnName === name ) {
782 | this.eventsUserCollection[ k ]();
783 | }
784 | }
785 | }
786 | };
787 |
788 | stVideo.prototype.play = function() {
789 | if ( this.isError ) {
790 | return;
791 | }
792 |
793 | this.lastTime = Date.now();
794 |
795 | if ( this.useCanvas ) {
796 | this.canvasControl( 'play' );
797 | } else {
798 | this.video.play();
799 | }
800 | };
801 |
802 | stVideo.prototype.pause = function() {
803 | if ( this.isError ) {
804 | return;
805 | }
806 |
807 | if ( this.isPlaying ) {
808 | if ( this.useCanvas ) {
809 | this.canvasControl( 'pause' );
810 | } else {
811 | this.video.pause();
812 | }
813 | }
814 | };
815 |
816 | stVideo.prototype.changeState = function( action, value ) {
817 | var ec = this.element.classList;
818 |
819 | if ( action === 'play' ) {
820 | this.isPlaying = value;
821 |
822 | if ( value ) {
823 | ec.add( this.classNames.isPlaying );
824 |
825 | this.eventCallback( 'play' );
826 | } else {
827 | ec.remove( this.classNames.isPlaying );
828 | }
829 | }
830 |
831 | if ( action === 'pause' ) {
832 | this.isPaused = value;
833 |
834 | if ( value ) {
835 | ec.add( this.classNames.isPaused );
836 |
837 | this.eventCallback( 'pause' );
838 | } else {
839 | ec.remove( this.classNames.isPaused );
840 | }
841 | }
842 |
843 | if ( action === 'end' ) {
844 | this.isEnded = value;
845 |
846 | if ( value ) {
847 | ec.add( this.classNames.isEnded );
848 |
849 | this.eventCallback( 'end' );
850 | } else {
851 | ec.remove( this.classNames.isEnded );
852 | }
853 | }
854 |
855 | if ( action === 'muted' ) {
856 | this.isMuted = value;
857 |
858 | if ( value ) {
859 | ec.add( this.classNames.isMuted );
860 |
861 | this.eventCallback( 'muted' );
862 | } else {
863 | ec.remove( this.classNames.isMuted );
864 | }
865 | }
866 |
867 | if ( action === 'handle' ) {
868 | this.isMuted = value;
869 |
870 | if ( value ) {
871 | ec.add( this.classNames.isHandle );
872 | } else {
873 | ec.remove( this.classNames.isHandle );
874 | }
875 | }
876 | };
877 |
878 | stVideo.prototype.destroy = function() {
879 |
880 | };
881 |
882 | return stVideo;
883 | } );
884 |
--------------------------------------------------------------------------------