/**
* @file text-track-settings.js
*/
從“全局/窗口”導入窗口;
從 '../component' 導入組件;
從 '../modal-dialog' 導入 ModalDialog;
從'../utils/dom'導入{createEl};
從 '../utils/obj' 導入 * 作為 Obj;
從 '../utils/log' 導入日誌;
const LOCAL_STORAGE_KEY = 'vjs-text-track-settings';
const COLOR_BLACK = ['#000', '黑色'];
const COLOR_BLUE = ['#00F', '藍色'];
const COLOR_CYAN = ['#0FF', '青色'];
const COLOR_GREEN = ['#0F0', '綠色'];
const COLOR_MAGENTA = ['#F0F', '洋紅色'];
const COLOR_RED = ['#F00', '紅色'];
const COLOR_WHITE = ['#FFF', '白色'];
const COLOR_YELLOW = ['#FF0', '黃色'];
const OPACITY_OPAQUE = ['1', '不透明'];
const OPACITY_SEMI = ['0.5', '半透明'];
const OPACITY_TRANS = ['0', '透明'];
// 該組件 DOM 中各種 <select> 元素的配置。
//
// 可能的鍵包括:
//
// `默認`:
// 默認選項索引。如果不為零,則只需要提供。
// `解析器`:
// 一個函數,用於解析所選選項中的值
// 自定義方式。
// `選擇器`:
// 用於查找關聯的 <select> 元素的選擇器。
const selectConfigs = {
背景顏色: {
選擇器:'.vjs-bg-color > 選擇',
id: '字幕-背景顏色-%s',
標籤:'顏色',
選項: [
顏色:黑色,
白顏色,
紅色,
顏色_綠色,
顏色_藍色,
顏色_黃色,
COLOR_MAGENTA,
顏色_青色
]
},
背景不透明度:{
選擇器:'.vjs-bg-opacity > 選擇',
id: '字幕-背景-不透明度-%s',
標籤:'透明度',
選項: [
不透明不透明,
OPACITY_SEMI,
OPACITY_TRANS
]
},
顏色: {
選擇器:'.vjs-fg-color > 選擇',
id: '字幕-前景色-%s',
標籤:'顏色',
選項: [
白顏色,
顏色:黑色,
紅色,
顏色_綠色,
顏色_藍色,
顏色_黃色,
COLOR_MAGENTA,
顏色_青色
]
},
邊緣樣式:{
選擇器:'.vjs-edge-style > 選擇',
編號:“%s”,
標籤:'文本邊緣樣式',
選項: [
['無', '無'],
['提高', '提高'],
['沮喪', '沮喪'],
['制服', '制服'],
['陰影', '陰影']
]
},
字體系列: {
選擇器:'.vjs-font-family > 選擇',
id: '字幕-字體系列-%s',
標籤:'字體系列',
選項: [
['proportionalSansSerif', 'Proportional Sans-Serif'],
['monospaceSansSerif', 'Monospace Sans-Serif'],
['proportionalSerif', 'Proportional Serif'],
['monospaceSerif', 'Monospace Serif'],
['休閒', '休閒'],
['腳本', '腳本'],
['小型大寫字母','小型大寫字母']
]
},
字體百分比:{
選擇器:'.vjs-font-percent > 選擇',
id: '字幕-字體大小-%s',
標籤:'字體大小',
選項: [
['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%']
]、
默認:2、
解析器:(v)=> v === '1.00'?空:數(v)
},
文本不透明度:{
選擇器:'.vjs-text-opacity > 選擇',
id: '字幕-前景-不透明度-%s',
標籤:'透明度',
選項: [
不透明不透明,
OPACITY_SEMI
]
},
// 此對象的選項定義如下。
窗口顏色:{
選擇器:'.vjs-window-color > 選擇',
id: '字幕窗口顏色-%s',
標籤:'顏色'
},
// 此對象的選項定義如下。
窗口透明度:{
選擇器:'.vjs-window-opacity > 選擇',
id: '字幕-窗口-不透明度-%s',
標籤:'透明度',
選項: [
OPACITY_TRANS,
OPACITY_SEMI,
不透明_不透明
]
}
};
selectConfigs.windowColor.options = selectConfigs.backgroundColor.options;
/**
* 獲取期權的實際價值。
*
* @param {string} 值
* 獲得的價值
*
* @param {函數} [解析器]
* 調整值的可選功能。
*
* @return {混合}
* - 如果不存在任何值,則為 `undefined`
* - 如果給定值為“無”,則為“未定義”。
* - 否則將是實際值。
*
* @私人的
*/
函數 parseOptionValue(值,解析器){
如果(解析器){
值=解析器(值);
}
如果(價值&&價值!=='無'){
返回值;
}
}
/**
* 獲取 <select> 元素中選定的 <option> 元素的值。
*
* @param {元素} el
* 要查看的元素
*
* @param {函數} [解析器]
* 調整值的可選功能。
*
* @return {混合}
* - 如果不存在任何值,則為 `undefined`
* - 如果給定值為“無”,則為“未定義”。
* - 否則將是實際值。
*
* @私人的
*/
函數 getSelectedOptionValue(el,解析器){
const value = el.options[el.options.selectedIndex].value;
返回 parseOptionValue(值,解析器);
}
/**
* 在一個基於 <select> 元素的 <option> 元素中設置被選擇的 <option> 元素
* 給定值。
*
* @param {元素} el
* 要查看的元素。
*
* @param {string} 值
* 要查看的屬性。
*
* @param {函數} [解析器]
* 比較前調整值的可選功能。
*
* @私人的
*/
函數 setSelectedOption(el,值,解析器){
如果(!值){
返回;
}
對於(讓我 = 0; 我是 < 選項。長度; 我 ++){
如果 (parseOptionValue(el.options[i].value, parser) === value) {
el.selectedIndex = i;
休息;
}
}
}
/**
* 操縱文本軌道設置。
*
* @extends 模態對話框
*/
類 TextTrackSettings 擴展 ModalDialog {
/**
* 創建此類的一個實例。
*
* @param {Player} 播放器
* 此類應附加到的 `Player`。
*
* @param {對象} [選項]
* 播放器選項的鍵/值存儲。
*/
構造函數(播放器,選項){
options.temporary = false;
超級(播放器,選項);
this.updateDisplay = this.updateDisplay.bind(this);
// 填充模式並假裝我們已經打開它
這個.填充();
this.hasBeenOpened_ = this.hasBeenFilled_ = true;
this.endDialog = createEl('p', {
className: 'vjs-control-text',
textContent: this.localize('對話框窗口結束。')
});
this.el().appendChild(this.endDialog);
this.setDefaults();
// 如果沒有傳入子選項,則從播放器選項中獲取 `persistTextTrackSettings`
如果(選項。persistTextTrackSettings ===未定義){
this.options_.persistTextTrackSettings = this.options_.playerOptions.persistTextTrackSettings;
}
this.on(this.$('.vjs-done-button'), 'click', () => {
這個.saveSettings();
這個。關閉();
});
this.on(this.$('.vjs-default-button'), 'click', () => {
this.setDefaults();
這個.updateDisplay();
});
Obj.each(selectConfigs, config => {
this.on(this.$(config.selector), 'change', this.updateDisplay);
});
如果(this.options_.persistTextTrackSettings){
這個.restoreSettings();
}
}
處置(){
this.endDialog = null;
super.dispose();
}
/**
* 創建一個帶有配置選項的 <select> 元素。
*
* @param {string} 鍵
* 創建期間使用的配置密鑰。
*
* @return {字符串}
* 一個 HTML 字符串。
*
* @私人的
*/
createElSelect_(key, legendId = '', type = 'label') {
const config = selectConfigs[key];
const id = config.id.replace('%s', this.id_);
const selectLabelledbyIds = [legendId, id].join(' ').trim();
返回 [
` < $ {類型} ID =「$ {ID}」類 =「$ {類型 === '標籤'?'vj-標籤 ':「}" >`,
this.localize(config.label),
`</${type}>`,
`<select aria-labelledby="${selectLabelledbyIds}">`
].
連接(config.options.map(o => {
const optionId = id + '-' + o[1].replace(/\\W+/g, '');
返回 [
`<option id="${optionId}" value="${o[0]}" `,
`aria-labelledby="${selectLabelledbyIds} ${optionId}">`,
this.localize(o[1]),
'</選項>'
]。加入('');
})).
concat('</select>').join('');
}
/**
* 為組件創建前景色元素
*
* @return {字符串}
* 一個 HTML 字符串。
*
* @私人的
*/
createElFgColor_() {
const legendId = `captions-text-legend-${this.id_}`;
返回 [
'<fieldset class="vjs-fg-color vjs-track-setting">',
`<legend id="${legendId}">`,
this.localize('文本'),
'</圖例>',
this.createElSelect_('color', legendId),
'<span class="vjs-text-opacity vjs-opacity">',
this.createElSelect_('textOpacity', legendId),
'</span>',
'</fieldset>'
]。加入('');
}
/**
* 為組件創建背景色元素
*
* @return {字符串}
* 一個 HTML 字符串。
*
* @私人的
*/
createElBgColor_() {
const legendId = `captions-background-${this.id_}`;
返回 [
'<fieldset class="vjs-bg-color vjs-track-setting">',
`<legend id="${legendId}">`,
this.localize('背景'),
'</圖例>',
this.createElSelect_('backgroundColor', legendId),
'<span class="vjs-bg-opacity vjs-opacity">',
this.createElSelect_('backgroundOpacity', legendId),
'</span>',
'</fieldset>'
]。加入('');
}
/**
* 為組件創建窗口顏色元素
*
* @return {字符串}
* 一個 HTML 字符串。
*
* @私人的
*/
createElWinColor_() {
const legendId = `captions-window-${this.id_}`;
返回 [
'<fieldset class="vjs-window-color vjs-track-setting">',
`<legend id="${legendId}">`,
this.localize('窗口'),
'</圖例>',
this.createElSelect_('windowColor', legendId),
'<span class="vjs-window-opacity vjs-opacity">',
this.createElSelect_('windowOpacity', legendId),
'</span>',
'</fieldset>'
]。加入('');
}
/**
* 為組件創建顏色元素
*
* @return {元素}
* 創建的元素
*
* @私人的
*/
createElColors_() {
返回 createEl('div', {
className: 'vjs-track-settings-colors',
內部HTML:[
這個.createElFgColor_(),
這個.createElBgColor_(),
this.createElWinColor_()
]。加入('')
});
}
/**
* 為組件創建字體元素
*
* @return {元素}
* 創建的元素。
*
* @私人的
*/
createElFont_() {
返回 createEl('div', {
className: 'vjs-track-settings-font',
內部HTML:[
'<fieldset class="vjs-font-percent vjs-track-setting">',
this.createElSelect_('fontPercent', '', 'legend'),
'</fieldset>',
'<fieldset class="vjs-edge-style vjs-track-setting">',
this.createElSelect_('edgeStyle', '', '圖例'),
'</fieldset>',
'<fieldset class="vjs-font-family vjs-track-setting">',
this.createElSelect_('fontFamily', '', '圖例'),
'</fieldset>'
]。加入('')
});
}
/**
* 為組件創建控件
*
* @return {元素}
* 創建的元素。
*
* @私人的
*/
createElControls_() {
const defaultsDescription = this.localize('恢復所有設置為默認值');
返回 createEl('div', {
className: 'vjs-track-settings-controls',
內部HTML:[
`<button type="button" class="vjs-default-button" title="${defaultsDescription}">`,
this.localize('重置'),
`<span class="vjs-control-text"> ${defaultsDescription}</span>`,
'</button>',
`<button type="button" class="vjs-done-button">${this.localize('Done')}</button>`
]。加入('')
});
}
內容() {
返回 [
這個.createElColors_(),
這個.createElFont_(),
this.createElControls_()
];
}
標籤() {
return this.localize('字幕設置對話框');
}
描述() {
return this.localize('對話窗口的開始。Escape 將取消並關閉窗口。');
}
buildCSSClass() {
返回 super.buildCSSClass() + 'vjs-text-track-settings';
}
/**
* 獲取文本軌道設置對象(或空值)。
*
* @return {對象}
* 具有從 DOM 或 localStorage 解析的配置值的對象。
*/
getValues() {
返回 Obj.reduce(selectConfigs, (accum, config, key) => {
const value = getSelectedOptionValue(this.$(config.selector), config.parser);
如果(值!==未定義){
累積 [鍵] = 值;
}
返回累積;
}, {});
}
/**
* 從值對象設置文本軌道設置。
*
* @param {Object} 值
* 具有從 DOM 或 localStorage 解析的配置值的對象。
*/
設置值(值){
Obj.each(selectConfigs, (config, key) => {
setSelectedOption(this.$(config.selector), values[key], config.parser);
});
}
/**
* 將所有 `<select>` 元素設置為其默認值。
*/
設置默認值(){
Obj.each(selectConfigs, (config) => {
常量索引 = 配置。擁有屬性('默認')?配置. 默認值:0;
this.$(config.selector).selectedIndex = index;
});
}
/**
* 從 localStorage 恢復 texttrack 設置
*/
恢復設置(){
讓價值觀;
嘗試{
values = JSON.parse(window.localStorage.getItem(LOCAL_STORAGE_KEY));
} 抓住(錯誤){
日誌警告(錯誤);
}
如果(值){
this.setValues(值);
}
}
/**
* 將文本軌道設置保存到 localStorage
*/
保存設置() {
如果(!this.options_.persistTextTrackSettings){
返回;
}
常量值 = this.getValues();
嘗試{
如果(對象.keys(值).length){
window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
}其他{
window.localStorage.removeItem(LOCAL_STORAGE_KEY);
}
} 抓住(錯誤){
日誌警告(錯誤);
}
}
/**
*更新文本軌道設置的顯示
*/
更新顯示(){
const ttDisplay = this.player_.getChild('textTrackDisplay');
如果(ttDisplay){
ttDisplay.updateDisplay();
}
}
/**
* 有條件地模糊元素並重新聚焦字幕按鈕
*
* @私人的
*/
條件模糊_() {
this.previouslyActiveEl_ = null;
const cb = this.player_.controlBar;
const subsCapsBtn = cb && cb.subsCapsButton;
const ccBtn = cb && cb.captionsButton;
如果(subsCapsBtn){
subsCapsBtn.focus();
} 否則如果(ccBtn){
ccBtn.focus();
}
}
}
Component.registerComponent('TextTrackSettings', TextTrackSettings);
導出默認的 TextTrackSettings;