/**
* @파일 메뉴.js
*/
'../component.js'에서 컴포넌트 가져오기;
'글로벌/문서'에서 문서 가져오기;
import * as Dom from '../utils/dom.js';
import * as Events from '../utils/events.js';
'키코드'에서 키코드 가져오기;
/**
* Menu 컴포넌트는 자막과 팝업 메뉴를 만드는 데 사용됩니다.
* 캡션 선택 메뉴.
*
* @extends 컴포넌트
*/
클래스 메뉴 확장 구성 요소 {
/**
* 이 클래스의 인스턴스를 만듭니다.
*
* @param {플레이어} 플레이어
* 이 구성 요소가 연결되어야 하는 플레이어
*
* @param {객체} [옵션]
* 옵션 이름 및 값의 개체
*
*/
생성자(플레이어, 옵션) {
super(플레이어, 옵션);
if (옵션) {
this.menuButton_ = options.menuButton;
}
this.focusedChild_ = -1;
this.on('키다운', (e) => this.handleKeyDown(e));
// 모든 메뉴 항목 인스턴스는 메뉴 컨테이너에서 제공하는 동일한 흐림 처리기를 공유합니다.
this.boundHandleBlur_ = (e) => this.handleBlur(e);
this.boundHandleTapClick_ = (e) => this.handleTapClick(e);
}
/**
* {@link MenuItem}에 이벤트 리스너를 추가합니다.
*
* @param {객체} 컴포넌트
* 리스너를 추가할 `MenuItem`의 인스턴스.
*
*/
addEventListenerForItem(구성 요소) {
if (!(컴포넌트의 컴포넌트 인스턴스)) {
반품;
}
this.on(component, 'blur', this.boundHandleBlur_);
this.on(구성요소, ['탭', '클릭'], this.boundHandleTapClick_);
}
/**
* {@link MenuItem}에서 이벤트 리스너를 제거합니다.
*
* @param {객체} 컴포넌트
* 리스너를 제거하기 위한 `MenuItem`의 인스턴스.
*
*/
removeEventListenerForItem(구성 요소) {
if (!(컴포넌트의 컴포넌트 인스턴스)) {
반품;
}
this.off(컴포넌트, '블러', this.boundHandleBlur_);
this.off(컴포넌트, ['탭', '클릭'], this.boundHandleTapClick_);
}
/**
* 이 메서드는 컴포넌트가 추가되면 간접적으로 호출됩니다.
* 컴포넌트가 `addItem`에 의해 새 메뉴 인스턴스에 추가되기 전에.
* 이 경우 원래 메뉴 인스턴스는 구성 요소를 제거합니다.
* `removeChild` 호출.
*
* @param {객체} 컴포넌트
* `MenuItem`의 인스턴스
*/
removeChild(구성 요소) {
if (구성 요소 유형 === '문자열') {
구성 요소 = this.getChild(구성 요소);
}
this.removeEventListenerForItem(구성 요소);
super.removeChild(구성요소);
}
/**
* 메뉴에 {@link MenuItem}을 추가합니다.
*
* @param {객체|문자열} 구성요소
* 추가할 `MenuItem`의 이름 또는 인스턴스입니다.
*
*/
addItem(구성 요소) {
const childComponent = this.addChild(구성 요소);
경우 (자식 구성 요소) {
this.addEventListenerForItem(childComponent);
}
}
/**
* `Menu`의 DOM 요소를 만듭니다.
*
* @return {요소}
* 생성된 요소
*/
createEl() {
const contentElType = this.options_.contentElType || '울';
this.contentEl_ = Dom.createEl(contentElType, {
className: 'vjs-menu-content'
});
this.contentEl_.setAttribute('역할', '메뉴');
const el = super.createEl('div', {
추가: this.contentEl_,
className: 'vjs 메뉴'
});
el.appendChild(this.contentEl_);
// 클릭이 버블링되는 것을 방지합니다. 메뉴 버튼에 필요,
// 여기서 부모에 대한 클릭이 중요합니다.
Events.on(el, '클릭', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
});
반환 엘;
}
폐기() {
this.contentEl_ = null;
this.boundHandleBlur_ = null;
this.boundHandleTapClick_ = null;
super.dispose();
}
/**
* `MenuItem`이 포커스를 잃을 때 호출됩니다.
*
* @param {EventTarget~Event} 이벤트
* 이 함수를 호출하게 만든 `blur` 이벤트.
*
* @듣기 흐림
*/
handleBlur(이벤트) {
const relatedTarget = event.relatedTarget || document.activeElement;
// 사용자가 메뉴 외부를 클릭하면 메뉴 팝업 닫기
if (!this.children().some((요소) => {
return element.el() === relatedTarget;
})) {
const btn = this.menuButton_;
만약 (btn && btn.버튼누름_ && relatedTarget !== btn.el().firstChild) {
btn.unpressButton();
}
}
}
/**
* `MenuItem`이 클릭되거나 탭될 때 호출됩니다.
*
* @param {EventTarget~Event} 이벤트
* 이 함수를 호출한 `click` 또는 `tap` 이벤트.
*
* @listens 클릭, 탭
*/
handleTapClick(이벤트) {
// 연결된 MenuButton을 누르고 포커스를 다시 이동합니다.
if (this.menuButton_) {
this.menuButton_.unpressButton();
const childComponents = this.children();
if (!Array.isArray(childComponents)) {
반품;
}
const foundComponent = childComponents.filter(구성 요소 => component.el() === event.target)[0];
if (!foundComponent) {
반품;
}
// 항목이 캡션 설정 항목인 경우 메뉴 버튼에 초점을 맞추지 않음
// 포커스가 다른 곳으로 이동하기 때문에
if (foundComponent.name() !== 'CaptionSettingsMenuItem') {
this.menuButton_.focus();
}
}
}
/**
* 이 메뉴에서 `keydown` 이벤트를 처리합니다. 이 리스너는 생성자에 추가됩니다.
*
* @param {EventTarget~Event} 이벤트
* 메뉴에서 발생한 `keydown` 이벤트.
*
* @listens 키다운
*/
handleKeyDown(이벤트) {
// 왼쪽 및 아래쪽 화살표
if (keycode.isEventKey(event, 'Left') || keycode.isEventKey(event, 'Down')) {
event.preventDefault();
event.stopPropagation();
this.stepForward();
// 위쪽 및 오른쪽 화살표
} 그렇지 않으면 (keycode.isEventKey(event, 'Right') || keycode.isEventKey(event, 'Up')) {
event.preventDefault();
event.stopPropagation();
this.stepBack();
}
}
/**
* 키보드 사용자를 위한 다음(하위) 메뉴 항목으로 이동합니다.
*/
앞으로 단계() {
let stepChild = 0;
if (this.focusedChild_ !== 정의되지 않음) {
stepChild = this.focusedChild_ + 1;
}
this.focus(stepChild);
}
/**
* 키보드 사용자의 경우 이전(상위) 메뉴 항목으로 이동합니다.
*/
스텝백() {
let stepChild = 0;
if (this.focusedChild_ !== 정의되지 않음) {
stepChild = this.focusedChild_ - 1;
}
this.focus(stepChild);
}
/**
* `메뉴`에서 {@link MenuItem}에 포커스를 설정합니다.
*
* @param {객체|문자열} [항목=0]
* 자식 항목의 인덱스는 포커스를 설정합니다.
*/
포커스(항목 = 0) {
const children = this.children().slice();
const haveTitle = children.length && children[0].hasClass('vjs-menu-title');
if (haveTitle) {
children.shift();
}
if (어린이.길이 > 0) {
만약 (항목 < 0) {
항목 = 0;
} 그렇지 않으면 (항목 > = 어린이.길이) {
항목 = children.length - 1;
}
this.focusedChild_ = 항목;
children[item].el_.focus();
}
}
}
Component.registerComponent('메뉴', 메뉴);
기본 메뉴 내보내기;