summaryrefslogtreecommitdiff
path: root/javascript/videojs/src/js/tracks/text-track-settings.js
diff options
context:
space:
mode:
Diffstat (limited to 'javascript/videojs/src/js/tracks/text-track-settings.js')
-rw-r--r--javascript/videojs/src/js/tracks/text-track-settings.js471
1 files changed, 471 insertions, 0 deletions
diff --git a/javascript/videojs/src/js/tracks/text-track-settings.js b/javascript/videojs/src/js/tracks/text-track-settings.js
new file mode 100644
index 0000000..07973e8
--- /dev/null
+++ b/javascript/videojs/src/js/tracks/text-track-settings.js
@@ -0,0 +1,471 @@
+/**
+ * @file text-track-settings.js
+ */
+import window from 'global/window';
+import Component from '../component';
+import ModalDialog from '../modal-dialog';
+import {createEl} from '../utils/dom';
+import * as Obj from '../utils/obj';
+import log from '../utils/log';
+import TextTrackSettingsColors from './text-track-settings-colors';
+import TextTrackSettingsFont from './text-track-settings-font';
+import TrackSettingsControls from './text-track-settings-controls';
+
+/** @import Player from '../player' */
+
+const LOCAL_STORAGE_KEY = 'vjs-text-track-settings';
+
+const COLOR_BLACK = ['#000', 'Black'];
+const COLOR_BLUE = ['#00F', 'Blue'];
+const COLOR_CYAN = ['#0FF', 'Cyan'];
+const COLOR_GREEN = ['#0F0', 'Green'];
+const COLOR_MAGENTA = ['#F0F', 'Magenta'];
+const COLOR_RED = ['#F00', 'Red'];
+const COLOR_WHITE = ['#FFF', 'White'];
+const COLOR_YELLOW = ['#FF0', 'Yellow'];
+
+const OPACITY_OPAQUE = ['1', 'Opaque'];
+const OPACITY_SEMI = ['0.5', 'Semi-Transparent'];
+const OPACITY_TRANS = ['0', 'Transparent'];
+
+// Configuration for the various <select> elements in the DOM of this component.
+//
+// Possible keys include:
+//
+// `default`:
+// The default option index. Only needs to be provided if not zero.
+// `parser`:
+// A function which is used to parse the value from the selected option in
+// a customized way.
+// `selector`:
+// The selector used to find the associated <select> element.
+const selectConfigs = {
+ backgroundColor: {
+ selector: '.vjs-bg-color > select',
+ id: 'captions-background-color-%s',
+ label: 'Color',
+ options: [
+ COLOR_BLACK,
+ COLOR_WHITE,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_BLUE,
+ COLOR_YELLOW,
+ COLOR_MAGENTA,
+ COLOR_CYAN
+ ],
+ className: 'vjs-bg-color'
+ },
+
+ backgroundOpacity: {
+ selector: '.vjs-bg-opacity > select',
+ id: 'captions-background-opacity-%s',
+ label: 'Opacity',
+ options: [
+ OPACITY_OPAQUE,
+ OPACITY_SEMI,
+ OPACITY_TRANS
+ ],
+ className: 'vjs-bg-opacity vjs-opacity'
+ },
+
+ color: {
+ selector: '.vjs-text-color > select',
+ id: 'captions-foreground-color-%s',
+ label: 'Color',
+ options: [
+ COLOR_WHITE,
+ COLOR_BLACK,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_BLUE,
+ COLOR_YELLOW,
+ COLOR_MAGENTA,
+ COLOR_CYAN
+ ],
+ className: 'vjs-text-color'
+ },
+
+ edgeStyle: {
+ selector: '.vjs-edge-style > select',
+ id: '',
+ label: 'Text Edge Style',
+ options: [
+ ['none', 'None'],
+ ['raised', 'Raised'],
+ ['depressed', 'Depressed'],
+ ['uniform', 'Uniform'],
+ ['dropshadow', 'Drop shadow']
+ ]
+ },
+
+ fontFamily: {
+ selector: '.vjs-font-family > select',
+ id: '',
+ label: 'Font Family',
+ options: [
+ ['proportionalSansSerif', 'Proportional Sans-Serif'],
+ ['monospaceSansSerif', 'Monospace Sans-Serif'],
+ ['proportionalSerif', 'Proportional Serif'],
+ ['monospaceSerif', 'Monospace Serif'],
+ ['casual', 'Casual'],
+ ['script', 'Script'],
+ ['small-caps', 'Small Caps']
+ ]
+ },
+
+ fontPercent: {
+ selector: '.vjs-font-percent > select',
+ id: '',
+ label: 'Font Size',
+ options: [
+ ['0.50', '50%'],
+ ['0.75', '75%'],
+ ['1.00', '100%'],
+ ['1.25', '125%'],
+ ['1.50', '150%'],
+ ['1.75', '175%'],
+ ['2.00', '200%'],
+ ['3.00', '300%'],
+ ['4.00', '400%']
+ ],
+ default: 2,
+ parser: (v) => v === '1.00' ? null : Number(v)
+ },
+
+ textOpacity: {
+ selector: '.vjs-text-opacity > select',
+ id: 'captions-foreground-opacity-%s',
+ label: 'Opacity',
+ options: [
+ OPACITY_OPAQUE,
+ OPACITY_SEMI
+ ],
+ className: 'vjs-text-opacity vjs-opacity'
+ },
+
+ // Options for this object are defined below.
+ windowColor: {
+ selector: '.vjs-window-color > select',
+ id: 'captions-window-color-%s',
+ label: 'Color',
+ className: 'vjs-window-color'
+ },
+
+ // Options for this object are defined below.
+ windowOpacity: {
+ selector: '.vjs-window-opacity > select',
+ id: 'captions-window-opacity-%s',
+ label: 'Opacity',
+ options: [
+ OPACITY_TRANS,
+ OPACITY_SEMI,
+ OPACITY_OPAQUE
+ ],
+ className: 'vjs-window-opacity vjs-opacity'
+ }
+};
+
+selectConfigs.windowColor.options = selectConfigs.backgroundColor.options;
+
+/**
+ * Get the actual value of an option.
+ *
+ * @param {string} value
+ * The value to get
+ *
+ * @param {Function} [parser]
+ * Optional function to adjust the value.
+ *
+ * @return {*}
+ * - Will be `undefined` if no value exists
+ * - Will be `undefined` if the given value is "none".
+ * - Will be the actual value otherwise.
+ *
+ * @private
+ */
+function parseOptionValue(value, parser) {
+ if (parser) {
+ value = parser(value);
+ }
+
+ if (value && value !== 'none') {
+ return value;
+ }
+}
+
+/**
+ * Gets the value of the selected <option> element within a <select> element.
+ *
+ * @param {Element} el
+ * the element to look in
+ *
+ * @param {Function} [parser]
+ * Optional function to adjust the value.
+ *
+ * @return {*}
+ * - Will be `undefined` if no value exists
+ * - Will be `undefined` if the given value is "none".
+ * - Will be the actual value otherwise.
+ *
+ * @private
+ */
+function getSelectedOptionValue(el, parser) {
+ const value = el.options[el.options.selectedIndex].value;
+
+ return parseOptionValue(value, parser);
+}
+
+/**
+ * Sets the selected <option> element within a <select> element based on a
+ * given value.
+ *
+ * @param {Element} el
+ * The element to look in.
+ *
+ * @param {string} value
+ * the property to look on.
+ *
+ * @param {Function} [parser]
+ * Optional function to adjust the value before comparing.
+ *
+ * @private
+ */
+function setSelectedOption(el, value, parser) {
+ if (!value) {
+ return;
+ }
+
+ for (let i = 0; i < el.options.length; i++) {
+ if (parseOptionValue(el.options[i].value, parser) === value) {
+ el.selectedIndex = i;
+ break;
+ }
+ }
+}
+
+/**
+ * Manipulate Text Tracks settings.
+ *
+ * @extends ModalDialog
+ */
+class TextTrackSettings extends ModalDialog {
+
+ /**
+ * Creates an instance of this class.
+ *
+ * @param {Player} player
+ * The `Player` that this class should be attached to.
+ *
+ * @param {Object} [options]
+ * The key/value store of player options.
+ */
+ constructor(player, options) {
+ options.temporary = false;
+
+ super(player, options);
+
+ this.updateDisplay = this.updateDisplay.bind(this);
+
+ // fill the modal and pretend we have opened it
+ this.fill();
+ this.hasBeenOpened_ = this.hasBeenFilled_ = true;
+
+ this.renderModalComponents(player);
+
+ this.endDialog = createEl('p', {
+ className: 'vjs-control-text',
+ textContent: this.localize('End of dialog window.')
+ });
+ this.el().appendChild(this.endDialog);
+
+ this.setDefaults();
+
+ // Grab `persistTextTrackSettings` from the player options if not passed in child options
+ if (options.persistTextTrackSettings === undefined) {
+ this.options_.persistTextTrackSettings = this.options_.playerOptions.persistTextTrackSettings;
+ }
+
+ this.bindFunctionsToSelectsAndButtons();
+
+ if (this.options_.persistTextTrackSettings) {
+ this.restoreSettings();
+ }
+ }
+
+ renderModalComponents(player) {
+ const textTrackSettingsColors = new TextTrackSettingsColors(
+ player,
+ {
+ textTrackComponentid: this.id_,
+ selectConfigs,
+ fieldSets:
+ [
+ ['color', 'textOpacity'],
+ ['backgroundColor', 'backgroundOpacity'],
+ ['windowColor', 'windowOpacity']
+ ]
+ }
+ );
+
+ this.addChild(textTrackSettingsColors);
+
+ const textTrackSettingsFont = new TextTrackSettingsFont(
+ player,
+ {
+ textTrackComponentid: this.id_,
+ selectConfigs,
+ fieldSets:
+ [
+ ['fontPercent'],
+ ['edgeStyle'],
+ ['fontFamily']
+ ]
+ }
+ );
+
+ this.addChild(textTrackSettingsFont);
+
+ const trackSettingsControls = new TrackSettingsControls(player);
+
+ this.addChild(trackSettingsControls);
+ }
+
+ bindFunctionsToSelectsAndButtons() {
+ this.on(this.$('.vjs-done-button'), ['click', 'tap'], () => {
+ this.saveSettings();
+ this.close();
+ });
+
+ this.on(this.$('.vjs-default-button'), ['click', 'tap'], () => {
+ this.setDefaults();
+ this.updateDisplay();
+ });
+
+ Obj.each(selectConfigs, config => {
+ this.on(this.$(config.selector), 'change', this.updateDisplay);
+ });
+ }
+
+ dispose() {
+ this.endDialog = null;
+
+ super.dispose();
+ }
+
+ label() {
+ return this.localize('Caption Settings Dialog');
+ }
+
+ description() {
+ return this.localize('Beginning of dialog window. Escape will cancel and close the window.');
+ }
+
+ buildCSSClass() {
+ return super.buildCSSClass() + ' vjs-text-track-settings';
+ }
+
+ /**
+ * Gets an object of text track settings (or null).
+ *
+ * @return {Object}
+ * An object with config values parsed from the DOM or localStorage.
+ */
+ getValues() {
+ return Obj.reduce(selectConfigs, (accum, config, key) => {
+ const value = getSelectedOptionValue(this.$(config.selector), config.parser);
+
+ if (value !== undefined) {
+ accum[key] = value;
+ }
+
+ return accum;
+ }, {});
+ }
+
+ /**
+ * Sets text track settings from an object of values.
+ *
+ * @param {Object} values
+ * An object with config values parsed from the DOM or localStorage.
+ */
+ setValues(values) {
+ Obj.each(selectConfigs, (config, key) => {
+ setSelectedOption(this.$(config.selector), values[key], config.parser);
+ });
+ }
+
+ /**
+ * Sets all `<select>` elements to their default values.
+ */
+ setDefaults() {
+ Obj.each(selectConfigs, (config) => {
+ const index = config.hasOwnProperty('default') ? config.default : 0;
+
+ this.$(config.selector).selectedIndex = index;
+ });
+ }
+
+ /**
+ * Restore texttrack settings from localStorage
+ */
+ restoreSettings() {
+ let values;
+
+ try {
+ values = JSON.parse(window.localStorage.getItem(LOCAL_STORAGE_KEY));
+ } catch (err) {
+ log.warn(err);
+ }
+
+ if (values) {
+ this.setValues(values);
+ }
+ }
+
+ /**
+ * Save text track settings to localStorage
+ */
+ saveSettings() {
+ if (!this.options_.persistTextTrackSettings) {
+ return;
+ }
+
+ const values = this.getValues();
+
+ try {
+ if (Object.keys(values).length) {
+ window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
+ } else {
+ window.localStorage.removeItem(LOCAL_STORAGE_KEY);
+ }
+ } catch (err) {
+ log.warn(err);
+ }
+ }
+
+ /**
+ * Update display of text track settings
+ */
+ updateDisplay() {
+ const ttDisplay = this.player_.getChild('textTrackDisplay');
+
+ if (ttDisplay) {
+ ttDisplay.updateDisplay();
+ }
+ }
+
+ /**
+ * Repopulate dialog with new localizations on languagechange
+ */
+ handleLanguagechange() {
+ this.fill();
+ this.renderModalComponents(this.player_);
+ this.bindFunctionsToSelectsAndButtons();
+ }
+
+}
+
+Component.registerComponent('TextTrackSettings', TextTrackSettings);
+
+export default TextTrackSettings;