Browse Source

Merge branch 'master' of narrowizard/video_player into master

narrowizard 6 years ago
parent
commit
e005c9d0ad

+ 3
- 1
README.md View File

@@ -1,6 +1,8 @@
1 1
 Fork from [mderrick/react-html5video](https://github.com/mderrick/react-html5video)
2 2
 
3
-Add speed/playbackRate control
3
+## extension
4
++ Add speed/playbackRate control
5
++ ie9 support. (fullscreen feature only support ie11.)
4 6
 
5 7
 Install dependencies.
6 8
 

+ 0
- 51
scripts/deploy:demo.js View File

@@ -1,51 +0,0 @@
1
-/* eslint-disable no-console */
2
-
3
-const ghpages = require('gh-pages');
4
-const pkg = require('./../package.json');
5
-const path = require('path');
6
-const chalk = require('chalk');
7
-const fs = require('fs');
8
-const distPath = path.join(__dirname, '../demo/dist');
9
-
10
-const deploy = (options = {}) => {
11
-    ghpages.publish(distPath, Object.assign({
12
-        message: pkg.version
13
-    }, options), (err) => {
14
-        if (err) {
15
-            error([err]);
16
-            return;
17
-        }
18
-        console.log(chalk.green('Demo has succesfully deployed.'));
19
-    });
20
-};
21
-
22
-const error = (errs = []) => {
23
-    errs.forEach((err) => {
24
-        console.log(chalk.red(err));
25
-    });
26
-    process.exit(1);
27
-};
28
-
29
-try {
30
-    fs.accessSync(distPath, fs.F_OK);
31
-    if (process.env.TRAVIS) {
32
-        if (process.env.GITHUB_TOKEN) {
33
-            deploy({
34
-                repo: `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.TRAVIS_REPO_SLUG}.git`,
35
-                user: {
36
-                    name: 'Travis CI'
37
-                }
38
-            });
39
-        } else {
40
-            error(['process.env.GITHUB_TOKEN with "repo" access is required to deploy gh-pages.']);
41
-        }
42
-    } else {
43
-        // Deploys using git origin, username and email.
44
-        deploy();
45
-    }
46
-} catch (e) {
47
-    error([
48
-        `${distPath} does not exist.`,
49
-        'Please run "npm i && npm run i:demo && npm run build:demo" and try again.'
50
-    ]);
51
-}

+ 1
- 1
src/DefaultPlayer/Captions/Captions.js View File

@@ -3,7 +3,7 @@ import styles from './Captions.css';
3 3
 import ClosedCaptionIcon from './../Icon/caption_new.svg';
4 4
 
5 5
 export default ({ textTracks, onClick, onItemClick, className, ariaLabel }) => {
6
-    console.log('caption')
6
+    // console.log('caption')
7 7
     return (
8 8
         <div className={[
9 9
             styles.component,

+ 4
- 3
src/DefaultPlayer/DefaultPlayer.css View File

@@ -3,6 +3,7 @@
3 3
     font-family: Helvetica;
4 4
     font-size: 11px;
5 5
     background-color: #000;
6
+    width: 100%;
6 7
 }
7 8
 
8 9
 .video {
@@ -16,8 +17,8 @@
16 17
     right: 0;
17 18
     left: 0;
18 19
     height: 34px;
19
-    display: flex;
20
-    background-color: rgba(0,0,0,0.7);
20
+    display: block;
21
+    background-color: rgba(0, 0, 0, 0.7);
21 22
     opacity: 0;
22 23
     transition: opacity 0.2s;
23 24
 }
@@ -28,4 +29,4 @@
28 29
 
29 30
 .component:hover .controls {
30 31
     opacity: 1;
31
-}
32
+}

+ 63
- 63
src/DefaultPlayer/DefaultPlayer.js View File

@@ -54,83 +54,83 @@ const DefaultPlayer = ({
54 54
             styles.component,
55 55
             className
56 56
         ].join(' ')}
57
-        style={style}>
57
+            style={style}>
58 58
             <video
59 59
                 className={styles.video}
60 60
                 {...restProps}>
61
-                { children }
61
+                {children}
62 62
             </video>
63 63
             <Overlay
64 64
                 onClick={onPlayPauseClick}
65 65
                 {...video} />
66
-            { controls && controls.length && !video.error
66
+            {controls && controls.length && !video.error
67 67
                 ? <div className={styles.controls}>
68
-                        { controls.map((control, i) => {
69
-                            switch (control) {
70
-                                case 'Seek':
71
-                                    return <Seek
68
+                    {controls.map((control, i) => {
69
+                        switch (control) {
70
+                            case 'Seek':
71
+                                return <Seek
72
+                                    key={i}
73
+                                    ariaLabel={copy.seek}
74
+                                    className={styles.seek}
75
+                                    onChange={onSeekChange}
76
+                                    {...video} />;
77
+                            case 'PlayPause':
78
+                                return <PlayPause
79
+                                    key={i}
80
+                                    ariaLabelPlay={copy.play}
81
+                                    ariaLabelPause={copy.pause}
82
+                                    onClick={onPlayPauseClick}
83
+                                    {...video} />;
84
+                            case 'Fullscreen':
85
+                                return <Fullscreen
86
+                                    key={i}
87
+                                    ariaLabel={copy.fullscreen}
88
+                                    onClick={onFullscreenClick}
89
+                                    onScreenClickCallback={onScreenClickCallback}
90
+                                    {...video} />;
91
+                            case 'Time':
92
+                                return <Time
93
+                                    key={i}
94
+                                    {...video} />;
95
+                            case 'Volume':
96
+                                return <Volume
97
+                                    key={i}
98
+                                    onClick={onVolumeClick}
99
+                                    onChange={onVolumeChange}
100
+                                    ariaLabelMute={copy.mute}
101
+                                    ariaLabelUnmute={copy.unmute}
102
+                                    ariaLabelVolume={copy.volume}
103
+                                    {...video} />;
104
+                            case 'Captions':
105
+                                return video.textTracks && video.textTracks.length
106
+                                    ? <Captions
72 107
                                         key={i}
73
-                                        ariaLabel={copy.seek}
74
-                                        className={styles.seek}
75
-                                        onChange={onSeekChange}
76
-                                        {...video} />;
77
-                                case 'PlayPause':
78
-                                    return <PlayPause
108
+                                        onClick={onCaptionsClick}
109
+                                        ariaLabel={copy.captions}
110
+                                        onItemClick={onCaptionsItemClick}
111
+                                        {...video} />
112
+                                    : null;
113
+                            case 'Speed':
114
+                                return playbackrates && playbackrates.length > 0
115
+                                    ? <Speed
79 116
                                         key={i}
80
-                                        ariaLabelPlay={copy.play}
81
-                                        ariaLabelPause={copy.pause}
82
-                                        onClick={onPlayPauseClick}
83
-                                        {...video} />;
84
-                                case 'Fullscreen':
85
-                                    return <Fullscreen
86
-                                        key={i}
87
-                                        ariaLabel={copy.fullscreen}
88
-                                        onClick={onFullscreenClick}
89
-                                        onScreenClickCallback={onScreenClickCallback}
90
-                                        {...video} />;
91
-                                case 'Time':
92
-                                    return <Time
93
-                                        key={i}
94
-                                        {...video} />;
95
-                                case 'Volume':
96
-                                    return <Volume
97
-                                        key={i}
98
-                                        onClick={onVolumeClick}
99
-                                        onChange={onVolumeChange}
100
-                                        ariaLabelMute={copy.mute}
101
-                                        ariaLabelUnmute={copy.unmute}
102
-                                        ariaLabelVolume={copy.volume}
103
-                                        {...video} />;
104
-                                case 'Captions':
105
-                                    return video.textTracks && video.textTracks.length
106
-                                        ? <Captions
107
-                                            key={i}
108
-                                            onClick={onCaptionsClick}
109
-                                            ariaLabel={copy.captions}
110
-                                            onItemClick={onCaptionsItemClick}
111
-                                            {...video}/>
112
-                                        : null;
113
-                                case 'Speed':
114
-                                    return playbackrates && playbackrates.length > 0
115
-                                        ? <Speed
116
-                                            key={i}
117
-                                            onClick={onSpeedClick}
118
-                                            ariaLabel={copy.captions}
119
-                                            onItemClick={onSpeedsItemClick}
120
-                                            playbackrates={playbackrates}
121
-                                            {...video}/>
122
-                                        : null;
123
-                                default:
124
-                                    return null;
125
-                            }
126
-                        }) }
127
-                    </div>
128
-                : null }
117
+                                        onClick={onSpeedClick}
118
+                                        ariaLabel={copy.captions}
119
+                                        onItemClick={onSpeedsItemClick}
120
+                                        playbackrates={playbackrates}
121
+                                        {...video} />
122
+                                    : null;
123
+                            default:
124
+                                return null;
125
+                        }
126
+                    })}
127
+                </div>
128
+                : null}
129 129
         </div>
130 130
     );
131 131
 };
132 132
 
133
-const controls = ['PlayPause', 'Seek', 'Time', 'Volume', 'Captions', 'Speed', 'Fullscreen'];
133
+const controls = ['PlayPause', 'Seek', 'Fullscreen', 'Speed', 'Volume', 'Time', 'Captions'];
134 134
 
135 135
 DefaultPlayer.defaultProps = {
136 136
     copy,

+ 5
- 2
src/DefaultPlayer/Fullscreen/Fullscreen.css View File

@@ -1,4 +1,7 @@
1
-.component {}
1
+.component {
2
+    float: right;
3
+    height: 34px;
4
+}
2 5
 
3 6
 .component:hover {
4 7
     background-color: #000;
@@ -23,4 +26,4 @@
23 26
 
24 27
 .icon {
25 28
     padding: 5px;
26
-}
29
+}

+ 5
- 1
src/DefaultPlayer/PlayPause/PlayPause.css View File

@@ -1,4 +1,8 @@
1
-.component {}
1
+.component {
2
+    float: left;
3
+    height: 34px;
4
+}
5
+
2 6
 
3 7
 .component:hover {
4 8
     background-color: #000;

+ 4
- 1
src/DefaultPlayer/Seek/Seek.css View File

@@ -1,5 +1,8 @@
1 1
 .component {
2
-    position: relative;
2
+    position: absolute;
3
+    left: 34px;
4
+    height: 34px;
5
+    right: 178px;
3 6
 }
4 7
 
5 8
 .track {

+ 5
- 5
src/DefaultPlayer/Speed/Speed.css View File

@@ -1,5 +1,7 @@
1 1
 .component {
2 2
     position: relative;
3
+    float: right;
4
+    height: 34px;
3 5
 }
4 6
 
5 7
 .component:hover {
@@ -29,10 +31,9 @@
29 31
 
30 32
 .speedList {
31 33
     position: absolute;
32
-    right: -9px;
33 34
     bottom: 100%;
34 35
     display: none;
35
-    background-color: rgba(0,0,0,0.7);
36
+    background-color: rgba(0, 0, 0, 0.7);
36 37
     list-style: none;
37 38
     padding: 0;
38 39
     margin: 0;
@@ -48,12 +49,11 @@
48 49
     cursor: pointer;
49 50
 }
50 51
 
51
-.activeSpeedItem,
52
-.speedItem:hover {
52
+.activeSpeedItem, .speedItem:hover {
53 53
     background: #000;
54 54
 }
55 55
 
56 56
 .activeSpeedItem {
57 57
     composes: speedItem;
58 58
     text-decoration: underline;
59
-}
59
+}

+ 1
- 1
src/DefaultPlayer/Speed/Speed.js View File

@@ -3,7 +3,7 @@ import styles from './Speed.css';
3 3
 import SpeedIcon from './../Icon/speed.svg';
4 4
 
5 5
 export default ({ playbackrates, onClick, onItemClick, className, ariaLabel }) => {
6
-    console.log('speed')
6
+    // console.log('speed')
7 7
     return (
8 8
         <div className={[
9 9
             styles.component,

+ 1
- 0
src/DefaultPlayer/Time/Time.css View File

@@ -2,6 +2,7 @@
2 2
     padding: 0 10px 0 10px;
3 3
     line-height: 35px;
4 4
     color: #fff;
5
+    float: right;
5 6
 }
6 7
 
7 8
 .current {

+ 3
- 2
src/DefaultPlayer/Volume/Volume.css View File

@@ -1,5 +1,7 @@
1 1
 .component {
2 2
     position: relative;
3
+    float: right;
4
+    height: 34px;
3 5
 }
4 6
 
5 7
 .component:hover {
@@ -51,8 +53,7 @@
51 53
     background-color: #3e3e3e;
52 54
 }
53 55
 
54
-.fill,
55
-.input {
56
+.fill, .input {
56 57
     position: absolute;
57 58
     right: 0;
58 59
     bottom: 0;

+ 12
- 7
src/video/api.js View File

@@ -91,14 +91,18 @@ export const toggleTracks = (() => {
91 91
         } else {
92 92
             showTrack({ textTracks }, previousTrack || textTracks[0]);
93 93
         }
94
-}})();
94
+    }
95
+})();
95 96
 
96 97
 export const showSpeed = (videoEl, state, speed) => {
97 98
     let playbackrates = state.playbackrates;
98
-    hideSpeeds(videoEl, {playbackrates});
99
+    hideSpeeds(videoEl, { playbackrates });
99 100
     speed.mode = speed.SHOWING || 'showing';
100
-
101
-    videoEl.dataset['playbackrates'] = JSON.stringify(playbackrates);
101
+    if (videoEl.dataset) {
102
+        videoEl.dataset['playbackrates'] = JSON.stringify(playbackrates);
103
+    } else {
104
+        videoEl.setAttribute("data-playbackrates", JSON.stringify(playbackrates));
105
+    }
102 106
     videoEl.playbackRate = speed.id;
103 107
 };
104 108
 
@@ -118,12 +122,13 @@ export const toggleSpeeds = (() => {
118 122
             .filter((item) => item.mode === 'showing')[0];
119 123
 
120 124
         if (currentSpeed) {
121
-            hideSpeeds(videoEl, {playbackrates});
125
+            hideSpeeds(videoEl, { playbackrates });
122 126
             previousSpeed = currentSpeed;
123 127
         } else {
124
-            showSpeed(videoEl, {playbackrates}, previousSpeed || playbackrates[0]);
128
+            showSpeed(videoEl, { playbackrates }, previousSpeed || playbackrates[0]);
125 129
         }
126
-}})();
130
+    }
131
+})();
127 132
 
128 133
 /**
129 134
  * Custom getter methods that are commonly used

+ 21
- 11
src/video/video.js View File

@@ -43,8 +43,12 @@ export default (
43 43
             this.setState(
44 44
                 PROPERTIES.reduce((p, c) => {
45 45
                     p[c] = this.videoEl && this.videoEl[c];
46
-                    if (c == 'playbackrates' && this.videoEl.dataset[c]) {
47
-                        p[c] = this.videoEl && JSON.parse(this.videoEl.dataset[c]);
46
+                    if (c == 'playbackrates' && this.videoEl) {
47
+                        if (this.videoEl.dataset) {
48
+                            p[c] = JSON.parse(this.videoEl.dataset[c]);
49
+                        } else {
50
+                            p[c] = JSON.parse(this.videoEl.getAttribute("data-" + c));
51
+                        }
48 52
                     }
49 53
                     return p;
50 54
                 }, {})
@@ -53,14 +57,18 @@ export default (
53 57
 
54 58
         bindEventsToUpdateState() {
55 59
             EVENTS.forEach(event => {
56
-                this.videoEl.addEventListener(event.toLowerCase(), this.updateState);
60
+                if (this.videoEl.addEventListener) {
61
+                    this.videoEl.addEventListener(event.toLowerCase(), this.updateState);
62
+                } else {
63
+                    this.videoEl.attachEvent("on" + event.toLowerCase(), this.updateState);
64
+                }
57 65
             });
58 66
 
59 67
             TRACKEVENTS.forEach(event => {
60 68
                 // TODO: JSDom does not have this method on
61 69
                 // `textTracks`. Investigate so we can test this without this check.
62
-                this.videoEl.textTracks.addEventListener
63
-                && this.videoEl.textTracks.addEventListener(event.toLowerCase(), this.updateState);
70
+                this.videoEl.textTracks && this.videoEl.textTracks.addEventListener
71
+                    && this.videoEl.textTracks.addEventListener(event.toLowerCase(), this.updateState);
64 72
             });
65 73
 
66 74
             // If <source> elements are used instead of a src attribute then
@@ -71,26 +79,28 @@ export default (
71 79
             const sources = this.videoEl.getElementsByTagName('source');
72 80
             if (sources.length) {
73 81
                 const lastSource = sources[sources.length - 1];
74
-                lastSource.addEventListener('error', this.updateState);
82
+                lastSource.addEventListener ? lastSource.addEventListener('error', this.updateState) : lastSource.attachEvent('error', this.updateState);
75 83
             }
76 84
         }
77 85
 
78 86
         unbindEvents() {
79 87
             EVENTS.forEach(event => {
80
-                this.videoEl.removeEventListener(event.toLowerCase(), this.updateState);
88
+                this.videoEl.removeEventListener ? this.videoEl.removeEventListener(event.toLowerCase(), this.updateState) :
89
+                    this.videoEl.detachEvent("on" + event.toLowerCase(), this.updateState);
81 90
             });
82 91
 
83 92
             TRACKEVENTS.forEach(event => {
84 93
                 // TODO: JSDom does not have this method on
85 94
                 // `textTracks`. Investigate so we can test this without this check.
86
-                this.videoEl.textTracks.removeEventListener
87
-                && this.videoEl.textTracks.removeEventListener(event.toLowerCase(), this.updateState);
95
+                this.videoEl.textTracks && this.videoEl.textTracks.removeEventListener
96
+                    && this.videoEl.textTracks.removeEventListener(event.toLowerCase(), this.updateState);
88 97
             });
89 98
 
90 99
             const sources = this.videoEl.getElementsByTagName('source');
91 100
             if (sources.length) {
92 101
                 const lastSource = sources[sources.length - 1];
93
-                lastSource.removeEventListener('error', this.updateState);
102
+                lastSource.removeEventListener ? lastSource.removeEventListener('error', this.updateState) :
103
+                    lastSource.detachEvent('onerror', this.updateState);
94 104
             }
95 105
         }
96 106
 
@@ -120,7 +130,7 @@ export default (
120 130
                 this.props
121 131
             );
122 132
             return (
123
-                <div ref={this.setRef.bind(this)} style={{height: '100%'}}>
133
+                <div ref={this.setRef.bind(this)} style={{ height: '100%' }}>
124 134
                     <BaseComponent
125 135
                         {...mergeProps(
126 136
                             stateProps,