narro 6 years ago
parent
commit
2a4cf48b4f

+ 3
- 1
README.md View File

1
 Fork from [mderrick/react-html5video](https://github.com/mderrick/react-html5video)
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
 Install dependencies.
7
 Install dependencies.
6
 
8
 

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

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

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

3
     font-family: Helvetica;
3
     font-family: Helvetica;
4
     font-size: 11px;
4
     font-size: 11px;
5
     background-color: #000;
5
     background-color: #000;
6
+    width: 100%;
6
 }
7
 }
7
 
8
 
8
 .video {
9
 .video {
16
     right: 0;
17
     right: 0;
17
     left: 0;
18
     left: 0;
18
     height: 34px;
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
     opacity: 0;
22
     opacity: 0;
22
     transition: opacity 0.2s;
23
     transition: opacity 0.2s;
23
 }
24
 }
28
 
29
 
29
 .component:hover .controls {
30
 .component:hover .controls {
30
     opacity: 1;
31
     opacity: 1;
31
-}
32
+}

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

54
             styles.component,
54
             styles.component,
55
             className
55
             className
56
         ].join(' ')}
56
         ].join(' ')}
57
-        style={style}>
57
+            style={style}>
58
             <video
58
             <video
59
                 className={styles.video}
59
                 className={styles.video}
60
                 {...restProps}>
60
                 {...restProps}>
61
-                { children }
61
+                {children}
62
             </video>
62
             </video>
63
             <Overlay
63
             <Overlay
64
                 onClick={onPlayPauseClick}
64
                 onClick={onPlayPauseClick}
65
                 {...video} />
65
                 {...video} />
66
-            { controls && controls.length && !video.error
66
+            {controls && controls.length && !video.error
67
                 ? <div className={styles.controls}>
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
                                         key={i}
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
                                         key={i}
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
         </div>
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
 DefaultPlayer.defaultProps = {
135
 DefaultPlayer.defaultProps = {
136
     copy,
136
     copy,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

91
         } else {
91
         } else {
92
             showTrack({ textTracks }, previousTrack || textTracks[0]);
92
             showTrack({ textTracks }, previousTrack || textTracks[0]);
93
         }
93
         }
94
-}})();
94
+    }
95
+})();
95
 
96
 
96
 export const showSpeed = (videoEl, state, speed) => {
97
 export const showSpeed = (videoEl, state, speed) => {
97
     let playbackrates = state.playbackrates;
98
     let playbackrates = state.playbackrates;
98
-    hideSpeeds(videoEl, {playbackrates});
99
+    hideSpeeds(videoEl, { playbackrates });
99
     speed.mode = speed.SHOWING || 'showing';
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
     videoEl.playbackRate = speed.id;
106
     videoEl.playbackRate = speed.id;
103
 };
107
 };
104
 
108
 
118
             .filter((item) => item.mode === 'showing')[0];
122
             .filter((item) => item.mode === 'showing')[0];
119
 
123
 
120
         if (currentSpeed) {
124
         if (currentSpeed) {
121
-            hideSpeeds(videoEl, {playbackrates});
125
+            hideSpeeds(videoEl, { playbackrates });
122
             previousSpeed = currentSpeed;
126
             previousSpeed = currentSpeed;
123
         } else {
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
  * Custom getter methods that are commonly used
134
  * Custom getter methods that are commonly used

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

43
             this.setState(
43
             this.setState(
44
                 PROPERTIES.reduce((p, c) => {
44
                 PROPERTIES.reduce((p, c) => {
45
                     p[c] = this.videoEl && this.videoEl[c];
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
                     return p;
53
                     return p;
50
                 }, {})
54
                 }, {})
53
 
57
 
54
         bindEventsToUpdateState() {
58
         bindEventsToUpdateState() {
55
             EVENTS.forEach(event => {
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
             TRACKEVENTS.forEach(event => {
67
             TRACKEVENTS.forEach(event => {
60
                 // TODO: JSDom does not have this method on
68
                 // TODO: JSDom does not have this method on
61
                 // `textTracks`. Investigate so we can test this without this check.
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
             // If <source> elements are used instead of a src attribute then
74
             // If <source> elements are used instead of a src attribute then
71
             const sources = this.videoEl.getElementsByTagName('source');
79
             const sources = this.videoEl.getElementsByTagName('source');
72
             if (sources.length) {
80
             if (sources.length) {
73
                 const lastSource = sources[sources.length - 1];
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
         unbindEvents() {
86
         unbindEvents() {
79
             EVENTS.forEach(event => {
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
             TRACKEVENTS.forEach(event => {
92
             TRACKEVENTS.forEach(event => {
84
                 // TODO: JSDom does not have this method on
93
                 // TODO: JSDom does not have this method on
85
                 // `textTracks`. Investigate so we can test this without this check.
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
             const sources = this.videoEl.getElementsByTagName('source');
99
             const sources = this.videoEl.getElementsByTagName('source');
91
             if (sources.length) {
100
             if (sources.length) {
92
                 const lastSource = sources[sources.length - 1];
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
                 this.props
130
                 this.props
121
             );
131
             );
122
             return (
132
             return (
123
-                <div ref={this.setRef.bind(this)} style={{height: '100%'}}>
133
+                <div ref={this.setRef.bind(this)} style={{ height: '100%' }}>
124
                     <BaseComponent
134
                     <BaseComponent
125
                         {...mergeProps(
135
                         {...mergeProps(
126
                             stateProps,
136
                             stateProps,