mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-24 17:35:10 +03:00
64896d70b0
This reflects changes in Google's policy on JavaScript license headers, which should be smaller to avoid increasing the size of the binary unnecessarily. This also updates the company name from "Google, Inc" to "Google LLC". Change-Id: I3f8b9ed3700b6351f43173d50c94d35c333e82b4
165 lines
4.1 KiB
JavaScript
165 lines
4.1 KiB
JavaScript
/** @license
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
|
|
goog.provide('shaka.ui.RangeElement');
|
|
|
|
goog.require('shaka.ui.Element');
|
|
goog.require('shaka.util.Dom');
|
|
|
|
|
|
/**
|
|
* A range element, built to work across browsers.
|
|
*
|
|
* In particular, getting styles to work right on IE requires a specific
|
|
* structure.
|
|
*
|
|
* This also handles the case where the range element is being manipulated and
|
|
* updated at the same time. This can happen when seeking during playback or
|
|
* when casting.
|
|
*
|
|
* @extends {shaka.ui.Element}
|
|
* @export
|
|
*/
|
|
shaka.ui.RangeElement = class extends shaka.ui.Element {
|
|
/**
|
|
* @param {!HTMLElement} parent
|
|
* @param {!shaka.ui.Controls} controls
|
|
* @param {!Array.<string>} containerClassNames
|
|
* @param {!Array.<string>} barClassNames
|
|
*/
|
|
constructor(parent, controls, containerClassNames, barClassNames) {
|
|
super(parent, controls);
|
|
|
|
/**
|
|
* This container is to support IE 11. See detailed notes in
|
|
* less/range_elements.less for a complete explanation.
|
|
* @protected {!HTMLElement}
|
|
*/
|
|
this.container = shaka.util.Dom.createHTMLElement('div');
|
|
this.container.classList.add('shaka-range-container');
|
|
this.container.classList.add(...containerClassNames);
|
|
|
|
/** @private {boolean} */
|
|
this.isChanging_ = false;
|
|
|
|
/** @protected {!HTMLInputElement} */
|
|
this.bar =
|
|
/** @type {!HTMLInputElement} */ (document.createElement('input'));
|
|
|
|
this.bar.classList.add('shaka-range-element');
|
|
this.bar.classList.add(...barClassNames);
|
|
this.bar.type = 'range';
|
|
// TODO(#2027): step=any causes keyboard nav problems on IE 11.
|
|
this.bar.step = 'any';
|
|
this.bar.min = '0';
|
|
this.bar.max = '1';
|
|
this.bar.value = '0';
|
|
|
|
this.container.appendChild(this.bar);
|
|
this.parent.appendChild(this.container);
|
|
|
|
this.eventManager.listen(this.bar, 'mousedown', () => {
|
|
this.isChanging_ = true;
|
|
this.onChangeStart();
|
|
});
|
|
|
|
this.eventManager.listen(this.bar, 'touchstart', (e) => {
|
|
this.isChanging_ = true;
|
|
this.setBarValueForTouch_(e);
|
|
this.onChangeStart();
|
|
});
|
|
|
|
this.eventManager.listen(this.bar, 'input', () => {
|
|
this.onChange();
|
|
});
|
|
|
|
this.eventManager.listen(this.bar, 'touchmove', (e) => {
|
|
this.setBarValueForTouch_(e);
|
|
this.onChange();
|
|
});
|
|
|
|
this.eventManager.listen(this.bar, 'touchend', (e) => {
|
|
this.isChanging_ = false;
|
|
this.setBarValueForTouch_(e);
|
|
this.onChangeEnd();
|
|
});
|
|
|
|
this.eventManager.listen(this.bar, 'mouseup', () => {
|
|
this.isChanging_ = false;
|
|
this.onChangeEnd();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {number} min
|
|
* @param {number} max
|
|
*/
|
|
setRange(min, max) {
|
|
this.bar.min = min;
|
|
this.bar.max = max;
|
|
}
|
|
|
|
/**
|
|
* Called when user interaction begins.
|
|
* To be overridden by subclasses.
|
|
*/
|
|
onChangeStart() {}
|
|
|
|
/**
|
|
* Called when a new value is set by user interaction.
|
|
* To be overridden by subclasses.
|
|
*/
|
|
onChange() {}
|
|
|
|
/**
|
|
* Called when user interaction ends.
|
|
* To be overridden by subclasses.
|
|
*/
|
|
onChangeEnd() {}
|
|
|
|
/** @return {number} */
|
|
getValue() {
|
|
return parseFloat(this.bar.value);
|
|
}
|
|
|
|
/** @param {number} value */
|
|
setValue(value) {
|
|
// The user interaction overrides any external values being pushed in.
|
|
if (this.isChanging_) {
|
|
return;
|
|
}
|
|
|
|
this.bar.value = value;
|
|
}
|
|
|
|
/**
|
|
* Synchronize the touch position with the range value.
|
|
* Comes in handy on iOS, where users have to grab the handle in order
|
|
* to start seeking.
|
|
* @param {Event} event
|
|
* @private
|
|
*/
|
|
setBarValueForTouch_(event) {
|
|
event.preventDefault();
|
|
|
|
const changedTouch = /** @type {TouchEvent} */ (event).changedTouches[0];
|
|
const rect = this.bar.getBoundingClientRect();
|
|
|
|
// Calculate the range value based on the touch position.
|
|
let value = (this.bar.max / rect.width) *
|
|
(changedTouch.clientX - rect.left);
|
|
|
|
// Keep value within bounds.
|
|
if (value < this.bar.min) {
|
|
value = this.bar.min;
|
|
} else if (value > this.bar.max) {
|
|
value = this.bar.max;
|
|
}
|
|
|
|
this.bar.value = value;
|
|
}
|
|
};
|