shaka-player 2.5.1 → 2.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.csslintrc +13 -0
- package/AUTHORS +3 -0
- package/CHANGELOG.md +156 -0
- package/CONTRIBUTORS +3 -0
- package/README.md +3 -0
- package/build/README.md +5 -5
- package/build/apps.py +3 -1
- package/build/build.py +5 -2
- package/build/check.py +17 -0
- package/build/compiler.py +49 -0
- package/build/conformance.textproto +1 -0
- package/build/docs.py +0 -6
- package/build/generateExterns.js +72 -20
- package/build/install-linux-prereqs.sh +4 -4
- package/build/shakaBuildHelpers.py +7 -8
- package/build/test.py +21 -9
- package/build/types/core +1 -0
- package/build/types/ui +6 -1
- package/demo/asset_card.js +129 -41
- package/demo/cast_receiver/receiver_app.css +27 -13
- package/demo/close_button.js +10 -15
- package/demo/common/asset.js +6 -6
- package/demo/common/assets.js +72 -14
- package/demo/config.js +28 -25
- package/demo/custom.js +20 -16
- package/demo/demo.less +107 -16
- package/demo/demo_uncompiled.js +33 -0
- package/demo/demo_utils.js +4 -3
- package/demo/front.js +12 -8
- package/demo/index.html +14 -17
- package/demo/input.js +30 -23
- package/demo/input_container.js +15 -11
- package/demo/load.js +5 -7
- package/demo/main.js +138 -49
- package/demo/search.js +40 -36
- package/demo/service_worker.js +1 -1
- package/demo/tooltip.js +16 -24
- package/dist/.csslintstamp +0 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +165 -152
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +165 -152
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +28 -11
- package/dist/receiver.compiled.debug.js +11 -11
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +11 -11
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.debug.externs.js +232 -102
- package/dist/shaka-player.compiled.debug.js +189 -165
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +232 -102
- package/dist/shaka-player.compiled.js +567 -553
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.debug.externs.js +338 -113
- package/dist/shaka-player.ui.debug.js +296 -276
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +338 -113
- package/dist/shaka-player.ui.js +685 -671
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +1 -0
- package/docs/tutorials/fairplay.md +77 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/manifest-parser.md +1 -1
- package/docs/tutorials/ui-customization.md +5 -2
- package/docs/tutorials/ui.md +10 -4
- package/docs/tutorials/welcome.md +2 -2
- package/externs/mediasession.js +16 -1
- package/externs/shaka/net.js +14 -4
- package/externs/shaka/player.js +136 -90
- package/externs/tippy.js +30 -0
- package/externs/webkitmediakeys.js +4 -0
- package/karma.conf.js +30 -24
- package/lib/cast/cast_proxy.js +94 -23
- package/lib/cast/cast_receiver.js +8 -1
- package/lib/dash/content_protection.js +33 -1
- package/lib/dash/dash_parser.js +13 -5
- package/lib/hls/hls_parser.js +20 -4
- package/lib/media/drm_engine.js +29 -2
- package/lib/media/media_source_engine.js +9 -6
- package/lib/media/play_rate_controller.js +14 -3
- package/lib/media/playhead.js +8 -3
- package/lib/media/streaming_engine.js +68 -20
- package/lib/media/transmuxer.js +2 -2
- package/lib/media/video_wrapper.js +8 -3
- package/lib/net/data_uri_plugin.js +5 -2
- package/lib/net/http_fetch_plugin.js +3 -3
- package/lib/net/http_plugin_utils.js +2 -4
- package/lib/net/http_xhr_plugin.js +2 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/offline_scheme.js +7 -2
- package/lib/player.js +18 -8
- package/lib/polyfill/input_event.js +7 -11
- package/lib/polyfill/mediasource.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +2 -72
- package/lib/text/cue.js +1 -1
- package/lib/text/ttml_text_parser.js +1 -1
- package/lib/util/config_utils.js +1 -0
- package/lib/util/error.js +45 -11
- package/lib/util/event_manager.js +211 -100
- package/lib/util/fairplay_utils.js +122 -0
- package/lib/util/i_releasable.js +1 -0
- package/lib/util/player_configuration.js +7 -0
- package/lib/util/pssh.js +41 -0
- package/lib/util/string_utils.js +42 -6
- package/lib/util/timer.js +1 -1
- package/package.json +33 -33
- package/roadmap.md +96 -0
- package/shaka-player.uncompiled.js +5 -1
- package/test/dash/dash_parser_content_protection_unit.js +35 -1
- package/test/dash/dash_parser_manifest_unit.js +60 -0
- package/test/hls/hls_live_unit.js +7 -1
- package/test/hls/hls_parser_unit.js +50 -0
- package/test/media/drm_engine_unit.js +10 -4
- package/test/media/media_source_engine_integration.js +12 -0
- package/test/media/media_source_engine_unit.js +3 -1
- package/test/media/playhead_unit.js +7 -5
- package/test/media/streaming_engine_unit.js +46 -1
- package/test/media/transmuxer_integration.js +13 -0
- package/test/net/data_uri_plugin_unit.js +13 -2
- package/test/net/http_plugin_unit.js +17 -12
- package/test/net/networking_engine_unit.js +17 -8
- package/test/offline/offline_scheme_unit.js +18 -8
- package/test/player_external.js +3 -2
- package/test/player_integration.js +94 -3
- package/test/player_src_equals_integration.js +2 -2
- package/test/player_unit.js +21 -8
- package/test/test/boot.js +20 -5
- package/test/test/externs/jasmine.js +48 -0
- package/test/test/util/expect_async_polyfill.js +145 -0
- package/test/test/util/fake_networking_engine.js +1 -0
- package/test/test/util/manifest_generator.js +2 -1
- package/test/test/util/test_scheme.js +34 -2
- package/test/test/util/ui_utils.js +41 -0
- package/test/test/util/util.js +16 -8
- package/test/ui/ui_unit.js +130 -4
- package/ui/audio_language_selection.js +17 -96
- package/ui/big_play_button.js +61 -0
- package/ui/controls.js +226 -335
- package/ui/controls.less +3 -5
- package/ui/element.js +24 -6
- package/ui/externs/ui.js +62 -9
- package/ui/fullscreen_button.js +2 -52
- package/ui/less/buttons.less +10 -16
- package/ui/less/containers.less +75 -20
- package/ui/less/general.less +18 -2
- package/ui/less/other_elements.less +2 -1
- package/ui/less/overflow_menu.less +11 -10
- package/ui/less/range_elements.less +12 -10
- package/ui/less/spinner.less +2 -0
- package/ui/overflow_menu.js +1 -1
- package/ui/pip_button.js +1 -1
- package/ui/{play_pause_button.js → play_button.js} +17 -47
- package/ui/presentation_time.js +17 -12
- package/ui/range_element.js +176 -0
- package/ui/resolution_selection.js +43 -106
- package/ui/seek_bar.js +204 -0
- package/ui/settings_menu.js +113 -0
- package/ui/small_play_button.js +73 -0
- package/ui/text_displayer.js +17 -14
- package/ui/text_selection.js +42 -107
- package/ui/ui.js +17 -40
- package/ui/volume_bar.js +40 -68
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
/* These control the color and size of the various pieces. */
|
|
40
40
|
@thumb-color: white;
|
|
41
41
|
@track-default-color: white;
|
|
42
|
-
@thumb-size:
|
|
43
|
-
@track-height:
|
|
42
|
+
@thumb-size: 12px;
|
|
43
|
+
@track-height: 4px;
|
|
44
44
|
|
|
45
45
|
/* The range container is the div that contains a range element.
|
|
46
46
|
* This div will act as a virtual track to allow us to style the track space.
|
|
@@ -51,8 +51,10 @@
|
|
|
51
51
|
|
|
52
52
|
/* Vertical margins to occupy the same space as the thumb. */
|
|
53
53
|
margin: (@thumb-size - @track-height)/2 6px;
|
|
54
|
+
|
|
54
55
|
/* Smaller height to contain the background for the virtual track. */
|
|
55
56
|
height: @track-height;
|
|
57
|
+
|
|
56
58
|
/* Rounded ends on the virtual track. */
|
|
57
59
|
border-radius: @track-height;
|
|
58
60
|
|
|
@@ -123,6 +125,7 @@
|
|
|
123
125
|
&::-webkit-slider-runnable-track {
|
|
124
126
|
.track();
|
|
125
127
|
}
|
|
128
|
+
|
|
126
129
|
&::-webkit-slider-thumb {
|
|
127
130
|
.thumb();
|
|
128
131
|
}
|
|
@@ -131,6 +134,7 @@
|
|
|
131
134
|
&::-moz-range-track {
|
|
132
135
|
.track();
|
|
133
136
|
}
|
|
137
|
+
|
|
134
138
|
&::-moz-range-thumb {
|
|
135
139
|
.thumb();
|
|
136
140
|
}
|
|
@@ -139,6 +143,7 @@
|
|
|
139
143
|
&::-ms-track {
|
|
140
144
|
.track();
|
|
141
145
|
}
|
|
146
|
+
|
|
142
147
|
&::-ms-thumb {
|
|
143
148
|
.thumb();
|
|
144
149
|
}
|
|
@@ -152,14 +157,17 @@
|
|
|
152
157
|
&::-ms-fill-lower {
|
|
153
158
|
.hidden();
|
|
154
159
|
}
|
|
160
|
+
|
|
155
161
|
&::-ms-fill-upper {
|
|
156
162
|
.hidden();
|
|
157
163
|
}
|
|
158
164
|
}
|
|
159
165
|
|
|
160
|
-
.shaka-
|
|
166
|
+
.shaka-range-container {
|
|
161
167
|
.range-container();
|
|
168
|
+
}
|
|
162
169
|
|
|
170
|
+
.shaka-volume-bar-container {
|
|
163
171
|
width: 100px;
|
|
164
172
|
|
|
165
173
|
/* Hide volume slider on mobile-sized screens. */
|
|
@@ -169,16 +177,10 @@
|
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
.shaka-seek-bar-container {
|
|
172
|
-
.range-container();
|
|
173
|
-
|
|
174
180
|
/* TODO: Document why! */
|
|
175
181
|
width: 96.5%;
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
.shaka-
|
|
179
|
-
.range-element();
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.shaka-volume-bar {
|
|
184
|
+
.shaka-range-element {
|
|
183
185
|
.range-element();
|
|
184
186
|
}
|
package/ui/less/spinner.less
CHANGED
package/ui/overflow_menu.js
CHANGED
|
@@ -64,7 +64,7 @@ goog.require('shaka.util.Dom');
|
|
|
64
64
|
|
|
65
65
|
for (let i = 0; i < backToOverflowMenuButtons.length; i++) {
|
|
66
66
|
const button = backToOverflowMenuButtons[i];
|
|
67
|
-
|
|
67
|
+
this.eventManager.listen(button, 'click', () => {
|
|
68
68
|
// Hide the submenus, display the overflow menu
|
|
69
69
|
this.controls.hideSettingsMenus();
|
|
70
70
|
shaka.ui.Utils.setDisplay(this.overflowMenu_, true);
|
package/ui/pip_button.js
CHANGED
|
@@ -100,7 +100,7 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
100
100
|
this.onLeavePictureInPicture_();
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
this.eventManager.listen(this.controls, '
|
|
103
|
+
this.eventManager.listen(this.controls, 'caststatuschanged', (e) => {
|
|
104
104
|
this.onCastStatusChange_(e);
|
|
105
105
|
});
|
|
106
106
|
|
|
@@ -16,10 +16,9 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
goog.provide('shaka.ui.
|
|
19
|
+
goog.provide('shaka.ui.PlayButton');
|
|
20
20
|
|
|
21
21
|
goog.require('shaka.ui.Element');
|
|
22
|
-
goog.require('shaka.ui.Enums');
|
|
23
22
|
goog.require('shaka.ui.Locales');
|
|
24
23
|
goog.require('shaka.ui.Localization');
|
|
25
24
|
goog.require('shaka.util.Dom');
|
|
@@ -27,10 +26,9 @@ goog.require('shaka.util.Dom');
|
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
28
|
* @extends {shaka.ui.Element}
|
|
30
|
-
* @final
|
|
31
29
|
* @export
|
|
32
30
|
*/
|
|
33
|
-
shaka.ui.
|
|
31
|
+
shaka.ui.PlayButton = class extends shaka.ui.Element {
|
|
34
32
|
/**
|
|
35
33
|
* @param {!HTMLElement} parent
|
|
36
34
|
* @param {!shaka.ui.Controls} controls
|
|
@@ -38,37 +36,30 @@ shaka.ui.PlayPauseButton = class extends shaka.ui.Element {
|
|
|
38
36
|
constructor(parent, controls) {
|
|
39
37
|
super(parent, controls);
|
|
40
38
|
|
|
41
|
-
/** @
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
44
|
-
this.button_.classList.add('material-icons');
|
|
45
|
-
this.parent.appendChild(this.button_);
|
|
46
|
-
|
|
47
|
-
this.updateIcon_();
|
|
48
|
-
this.updateAriaLabel_();
|
|
39
|
+
/** @protected {!HTMLElement} */
|
|
40
|
+
this.button = shaka.util.Dom.createHTMLElement('button');
|
|
41
|
+
this.parent.appendChild(this.button);
|
|
49
42
|
|
|
50
43
|
const LOCALE_UPDATED = shaka.ui.Localization.LOCALE_UPDATED;
|
|
51
44
|
this.eventManager.listen(this.localization, LOCALE_UPDATED, () => {
|
|
52
|
-
this.
|
|
45
|
+
this.updateAriaLabel();
|
|
53
46
|
});
|
|
54
47
|
|
|
55
48
|
const LOCALE_CHANGED = shaka.ui.Localization.LOCALE_CHANGED;
|
|
56
49
|
this.eventManager.listen(this.localization, LOCALE_CHANGED, () => {
|
|
57
|
-
this.
|
|
50
|
+
this.updateAriaLabel();
|
|
58
51
|
});
|
|
59
52
|
|
|
60
53
|
this.eventManager.listen(this.video, 'play', () => {
|
|
61
|
-
this.
|
|
62
|
-
this.updateIcon_();
|
|
54
|
+
this.updateAriaLabel();
|
|
63
55
|
});
|
|
64
56
|
|
|
65
57
|
this.eventManager.listen(this.video, 'pause', () => {
|
|
66
|
-
this.
|
|
67
|
-
this.updateIcon_();
|
|
58
|
+
this.updateAriaLabel();
|
|
68
59
|
});
|
|
69
60
|
|
|
70
|
-
this.eventManager.listen(this.
|
|
71
|
-
if (this.
|
|
61
|
+
this.eventManager.listen(this.button, 'click', () => {
|
|
62
|
+
if (this.isPaused()) {
|
|
72
63
|
this.video.play();
|
|
73
64
|
} else {
|
|
74
65
|
this.video.pause();
|
|
@@ -78,41 +69,20 @@ shaka.ui.PlayPauseButton = class extends shaka.ui.Element {
|
|
|
78
69
|
|
|
79
70
|
/**
|
|
80
71
|
* @return {boolean}
|
|
81
|
-
* @
|
|
72
|
+
* @protected
|
|
82
73
|
*/
|
|
83
|
-
|
|
74
|
+
isPaused() {
|
|
84
75
|
// The video element is in a paused state while seeking, but we don't count
|
|
85
76
|
// that.
|
|
86
77
|
return this.video.paused && !this.controls.isSeeking();
|
|
87
78
|
}
|
|
88
79
|
|
|
89
|
-
/** @
|
|
90
|
-
|
|
80
|
+
/** @protected */
|
|
81
|
+
updateAriaLabel() {
|
|
91
82
|
const LocIds = shaka.ui.Locales.Ids;
|
|
92
|
-
const label = this.
|
|
83
|
+
const label = this.isPaused() ? LocIds.PLAY : LocIds.PAUSE;
|
|
93
84
|
|
|
94
|
-
this.
|
|
85
|
+
this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
95
86
|
this.localization.resolve(label));
|
|
96
87
|
}
|
|
97
|
-
|
|
98
|
-
/** @private */
|
|
99
|
-
updateIcon_() {
|
|
100
|
-
const Icons = shaka.ui.Enums.MaterialDesignIcons;
|
|
101
|
-
this.button_.textContent = this.isPaused_() ? Icons.PLAY : Icons.PAUSE;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @implements {shaka.extern.IUIElement.Factory}
|
|
108
|
-
* @final
|
|
109
|
-
*/
|
|
110
|
-
shaka.ui.PlayPauseButton.Factory = class {
|
|
111
|
-
/** @override */
|
|
112
|
-
create(rootElement, controls) {
|
|
113
|
-
return new shaka.ui.PlayPauseButton(rootElement, controls);
|
|
114
|
-
}
|
|
115
88
|
};
|
|
116
|
-
|
|
117
|
-
shaka.ui.Controls.registerElement(
|
|
118
|
-
'play_pause', new shaka.ui.PlayPauseButton.Factory());
|
package/ui/presentation_time.js
CHANGED
|
@@ -37,7 +37,7 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
|
|
|
37
37
|
|
|
38
38
|
this.currentTime_ = shaka.util.Dom.createHTMLElement('button');
|
|
39
39
|
this.currentTime_.classList.add('shaka-current-time');
|
|
40
|
-
this.
|
|
40
|
+
this.setValue_('0:00');
|
|
41
41
|
this.parent.appendChild(this.currentTime_);
|
|
42
42
|
|
|
43
43
|
this.eventManager.listen(this.currentTime_, 'click', () => {
|
|
@@ -56,10 +56,18 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/** @private */
|
|
60
|
+
setValue_(value) {
|
|
61
|
+
// To avoid constant updates to the DOM, which makes debugging more
|
|
62
|
+
// difficult, only set the value if it has changed. If we don't do this
|
|
63
|
+
// check, the DOM updates constantly, this element flashes in the debugger
|
|
64
|
+
// in Chrome, and you can't make changes in the CSS panel.
|
|
65
|
+
if (value != this.currentTime_.textContent) {
|
|
66
|
+
this.currentTime_.textContent = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
59
69
|
|
|
60
|
-
/**
|
|
61
|
-
* @private
|
|
62
|
-
*/
|
|
70
|
+
/** @private */
|
|
63
71
|
updateTime_() {
|
|
64
72
|
const isSeeking = this.controls.isSeeking();
|
|
65
73
|
let displayTime = this.controls.getDisplayTime();
|
|
@@ -80,24 +88,21 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
|
|
|
80
88
|
// The button should only be clickable when it's live stream content, and
|
|
81
89
|
// the current play time is behind live edge.
|
|
82
90
|
if ((displayTime >= 1) || isSeeking) {
|
|
83
|
-
this.
|
|
84
|
-
'- ' + this.buildTimeString_(displayTime, showHour);
|
|
91
|
+
this.setValue_('- ' + this.buildTimeString_(displayTime, showHour));
|
|
85
92
|
this.currentTime_.disabled = false;
|
|
86
93
|
} else {
|
|
87
|
-
this.
|
|
88
|
-
this.localization.resolve(shaka.ui.Locales.Ids.LIVE);
|
|
94
|
+
this.setValue_(this.localization.resolve(shaka.ui.Locales.Ids.LIVE));
|
|
89
95
|
this.currentTime_.disabled = true;
|
|
90
96
|
}
|
|
91
97
|
} else {
|
|
92
98
|
let showHour = duration >= 3600;
|
|
93
99
|
|
|
94
|
-
this.
|
|
95
|
-
this.buildTimeString_(displayTime, showHour);
|
|
96
|
-
|
|
100
|
+
let value = this.buildTimeString_(displayTime, showHour);
|
|
97
101
|
if (duration) {
|
|
98
|
-
|
|
102
|
+
value += ' / ' +
|
|
99
103
|
this.buildTimeString_(duration, showHour);
|
|
100
104
|
}
|
|
105
|
+
this.setValue_(value);
|
|
101
106
|
this.currentTime_.disabled = true;
|
|
102
107
|
}
|
|
103
108
|
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2016 Google Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
goog.provide('shaka.ui.RangeElement');
|
|
20
|
+
|
|
21
|
+
goog.require('shaka.ui.Element');
|
|
22
|
+
goog.require('shaka.util.Dom');
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A range element, built to work across browsers.
|
|
27
|
+
*
|
|
28
|
+
* In particular, getting styles to work right on IE requires a specific
|
|
29
|
+
* structure.
|
|
30
|
+
*
|
|
31
|
+
* This also handles the case where the range element is being manipulated and
|
|
32
|
+
* updated at the same time. This can happen when seeking during playback or
|
|
33
|
+
* when casting.
|
|
34
|
+
*
|
|
35
|
+
* @extends {shaka.ui.Element}
|
|
36
|
+
* @export
|
|
37
|
+
*/
|
|
38
|
+
shaka.ui.RangeElement = class extends shaka.ui.Element {
|
|
39
|
+
/**
|
|
40
|
+
* @param {!HTMLElement} parent
|
|
41
|
+
* @param {!shaka.ui.Controls} controls
|
|
42
|
+
* @param {!Array.<string>} containerClassNames
|
|
43
|
+
* @param {!Array.<string>} barClassNames
|
|
44
|
+
*/
|
|
45
|
+
constructor(parent, controls, containerClassNames, barClassNames) {
|
|
46
|
+
super(parent, controls);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* This container is to support IE 11. See detailed notes in
|
|
50
|
+
* less/range_elements.less for a complete explanation.
|
|
51
|
+
* @protected {!HTMLElement}
|
|
52
|
+
*/
|
|
53
|
+
this.container = shaka.util.Dom.createHTMLElement('div');
|
|
54
|
+
this.container.classList.add('shaka-range-container');
|
|
55
|
+
this.container.classList.add(...containerClassNames);
|
|
56
|
+
|
|
57
|
+
/** @private {boolean} */
|
|
58
|
+
this.isChanging_ = false;
|
|
59
|
+
|
|
60
|
+
/** @protected {!HTMLInputElement} */
|
|
61
|
+
this.bar =
|
|
62
|
+
/** @type {!HTMLInputElement} */ (document.createElement('input'));
|
|
63
|
+
|
|
64
|
+
this.bar.classList.add('shaka-range-element');
|
|
65
|
+
this.bar.classList.add(...barClassNames);
|
|
66
|
+
this.bar.type = 'range';
|
|
67
|
+
// TODO(#2027): step=any causes keyboard nav problems on IE 11.
|
|
68
|
+
this.bar.step = 'any';
|
|
69
|
+
this.bar.min = '0';
|
|
70
|
+
this.bar.max = '1';
|
|
71
|
+
this.bar.value = '0';
|
|
72
|
+
|
|
73
|
+
this.container.appendChild(this.bar);
|
|
74
|
+
this.parent.appendChild(this.container);
|
|
75
|
+
|
|
76
|
+
this.eventManager.listen(this.bar, 'mousedown', () => {
|
|
77
|
+
this.isChanging_ = true;
|
|
78
|
+
this.onChangeStart();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
this.eventManager.listen(this.bar, 'touchstart', (e) => {
|
|
82
|
+
this.isChanging_ = true;
|
|
83
|
+
this.setBarValueForTouch_(e);
|
|
84
|
+
this.onChangeStart();
|
|
85
|
+
}, {passive: true});
|
|
86
|
+
|
|
87
|
+
this.eventManager.listen(this.bar, 'input', () => {
|
|
88
|
+
this.onChange();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
this.eventManager.listen(this.bar, 'touchmove', (e) => {
|
|
92
|
+
this.setBarValueForTouch_(e);
|
|
93
|
+
this.onChange();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this.eventManager.listen(this.bar, 'touchend', (e) => {
|
|
97
|
+
this.isChanging_ = false;
|
|
98
|
+
this.setBarValueForTouch_(e);
|
|
99
|
+
this.onChangeEnd();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
this.eventManager.listen(this.bar, 'mouseup', () => {
|
|
103
|
+
this.isChanging_ = false;
|
|
104
|
+
this.onChangeEnd();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {number} min
|
|
110
|
+
* @param {number} max
|
|
111
|
+
*/
|
|
112
|
+
setRange(min, max) {
|
|
113
|
+
this.bar.min = min;
|
|
114
|
+
this.bar.max = max;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Called when user interaction begins.
|
|
119
|
+
* To be overridden by subclasses.
|
|
120
|
+
*/
|
|
121
|
+
onChangeStart() {}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Called when a new value is set by user interaction.
|
|
125
|
+
* To be overridden by subclasses.
|
|
126
|
+
*/
|
|
127
|
+
onChange() {}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Called when user interaction ends.
|
|
131
|
+
* To be overridden by subclasses.
|
|
132
|
+
*/
|
|
133
|
+
onChangeEnd() {}
|
|
134
|
+
|
|
135
|
+
/** @return {number} */
|
|
136
|
+
getValue() {
|
|
137
|
+
return parseFloat(this.bar.value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** @param {number} value */
|
|
141
|
+
setValue(value) {
|
|
142
|
+
// The user interaction overrides any external values being pushed in.
|
|
143
|
+
if (this.isChanging_) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
this.bar.value = value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Synchronize the touch position with the range value.
|
|
152
|
+
* Comes in handy on iOS, where users have to grab the handle in order
|
|
153
|
+
* to start seeking.
|
|
154
|
+
* @param {Event} event
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
setBarValueForTouch_(event) {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
|
|
160
|
+
const changedTouch = /** @type {TouchEvent} */ (event).changedTouches[0];
|
|
161
|
+
const rect = this.bar.getBoundingClientRect();
|
|
162
|
+
|
|
163
|
+
// Calculate the range value based on the touch position.
|
|
164
|
+
let value = (this.bar.max / rect.width) *
|
|
165
|
+
(changedTouch.clientX - rect.left);
|
|
166
|
+
|
|
167
|
+
// Keep value within bounds.
|
|
168
|
+
if (value < this.bar.min) {
|
|
169
|
+
value = this.bar.min;
|
|
170
|
+
} else if (value > this.bar.max) {
|
|
171
|
+
value = this.bar.max;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.bar.value = value;
|
|
175
|
+
}
|
|
176
|
+
};
|