Audio button menu (#1302)
* Fix popup menus not stoping events * Ensure non-stale use of buttons * Enable popup menus on the popup/search pages * Add audio menu
This commit is contained in:
parent
9fbdb9757b
commit
ef577b8875
@ -70,6 +70,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="popup-menus"></div>
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
|
|
||||||
@ -96,6 +98,7 @@
|
|||||||
<script src="/mixed/js/hotkey-help-controller.js"></script>
|
<script src="/mixed/js/hotkey-help-controller.js"></script>
|
||||||
<script src="/mixed/js/hotkey-util.js"></script>
|
<script src="/mixed/js/hotkey-util.js"></script>
|
||||||
<script src="/mixed/js/media-loader.js"></script>
|
<script src="/mixed/js/media-loader.js"></script>
|
||||||
|
<script src="/mixed/js/popup-menu.js"></script>
|
||||||
<script src="/mixed/js/scroll.js"></script>
|
<script src="/mixed/js/scroll.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
<script src="/mixed/js/html-template-collection.js"></script>
|
<script src="/mixed/js/html-template-collection.js"></script>
|
||||||
|
@ -86,6 +86,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="popup-menus"></div>
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
<script src="/mixed/js/yomichan.js"></script>
|
<script src="/mixed/js/yomichan.js"></script>
|
||||||
@ -113,6 +115,7 @@
|
|||||||
<script src="/mixed/js/hotkey-util.js"></script>
|
<script src="/mixed/js/hotkey-util.js"></script>
|
||||||
<script src="/mixed/js/media-loader.js"></script>
|
<script src="/mixed/js/media-loader.js"></script>
|
||||||
<script src="/mixed/js/panel-element.js"></script>
|
<script src="/mixed/js/panel-element.js"></script>
|
||||||
|
<script src="/mixed/js/popup-menu.js"></script>
|
||||||
<script src="/mixed/js/scroll.js"></script>
|
<script src="/mixed/js/scroll.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
<script src="/mixed/js/html-template-collection.js"></script>
|
<script src="/mixed/js/html-template-collection.js"></script>
|
||||||
|
@ -1620,6 +1620,21 @@ button.footer-notification-close-button:active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Audio menu */
|
||||||
|
.audio-button-popup-menu[data-show-icons=false] .popup-menu-item-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.popup-menu-item-icon[data-icon=checkmark] {
|
||||||
|
background-color: var(--success-color);
|
||||||
|
}
|
||||||
|
.popup-menu-item-icon[data-icon=cross] {
|
||||||
|
background-color: var(--danger-color);
|
||||||
|
}
|
||||||
|
.popup-menu-item[data-source-in-options=false][data-valid=null] {
|
||||||
|
color: var(--text-color-light1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Conditional styles */
|
/* Conditional styles */
|
||||||
:root:not([data-enable-search-tags=true]) .tag[data-category=search] {
|
:root:not([data-enable-search-tags=true]) .tag[data-category=search] {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<button class="action-button action-view-note" hidden disabled data-icon="view-note" title="View added note" data-hotkey='["viewNote","title","View added note ({0})"]'></button>
|
<button class="action-button action-view-note" hidden disabled data-icon="view-note" title="View added note" data-hotkey='["viewNote","title","View added note ({0})"]'></button>
|
||||||
<button class="action-button action-add-note" hidden disabled data-icon="add-term-kanji" data-mode="term-kanji" title="Add expression" data-hotkey='["addNoteTermKanji","title","Add expression ({0})"]'></button>
|
<button class="action-button action-add-note" hidden disabled data-icon="add-term-kanji" data-mode="term-kanji" title="Add expression" data-hotkey='["addNoteTermKanji","title","Add expression ({0})"]'></button>
|
||||||
<button class="action-button action-add-note" hidden disabled data-icon="add-term-kana" data-mode="term-kana" title="Add reading" data-hotkey='["addNoteTermKana","title","Add reading ({0})"]'></button>
|
<button class="action-button action-add-note" hidden disabled data-icon="add-term-kana" data-mode="term-kana" title="Add reading" data-hotkey='["addNoteTermKana","title","Add reading ({0})"]'></button>
|
||||||
<button class="action-button action-play-audio" data-icon="play-audio" title="Play audio" data-title-default="Play audio" data-hotkey='["playAudio",["title","data-title-default"],"Play audio ({0})"]'><div class="action-button-badge icon" hidden></div></button>
|
<button class="action-button action-play-audio" data-icon="play-audio" title="Play audio" data-title-default="Play audio" data-hotkey='["playAudio",["title","data-title-default"],"Play audio ({0})"]' data-menu-position="left below h-cover v-cover"><div class="action-button-badge icon" hidden></div></button>
|
||||||
<span class="entry-current-indicator-icon" title="Current entry"></span>
|
<span class="entry-current-indicator-icon" title="Current entry"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="term-expression-list"></div>
|
<div class="term-expression-list"></div>
|
||||||
@ -44,7 +44,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="term-expression-details">
|
<div class="term-expression-details">
|
||||||
<button class="action-button action-play-audio" data-icon="play-audio" title="Play audio" data-title-default="Play audio" data-hotkey='["playAudio",["title","data-title-default"],"Play audio ({0})"]'><div class="action-button-badge icon" hidden></div></button>
|
<button class="action-button action-play-audio" data-icon="play-audio" title="Play audio" data-title-default="Play audio" data-hotkey='["playAudio",["title","data-title-default"],"Play audio ({0})"]' data-menu-position="right below h-cover v-cover"><div class="action-button-badge icon" hidden></div></button>
|
||||||
<div class="tags tag-list"></div>
|
<div class="tags tag-list"></div>
|
||||||
</div>
|
</div>
|
||||||
</div></template>
|
</div></template>
|
||||||
@ -149,4 +149,14 @@
|
|||||||
<div class="profile-list-item-name"></div>
|
<div class="profile-list-item-name"></div>
|
||||||
</label></template>
|
</label></template>
|
||||||
|
|
||||||
|
<!-- Popup menu -->
|
||||||
|
<template id="audio-button-popup-menu-template"><div class="popup-menu-container scan-disable audio-button-popup-menu" tabindex="-1" role="dialog"><div class="popup-menu popup-menu-auto-size"><div class="popup-menu-body">
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="jpod101"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">JapanesePod101</span></button>
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="jpod101-alternate"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">JapanesePod101 (Alternate)</span></button>
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="jisho"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">Jisho.org</span></button>
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="text-to-speech"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">Text-to-speech</span></button>
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="text-to-speech-reading"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">Text-to-speech (Kana reading)</span></button>
|
||||||
|
<button class="popup-menu-item" data-menu-action="playAudioFromSource" data-source="custom"><div class="popup-menu-item-icon icon" data-icon="none"></div><span class="popup-menu-item-label">Custom</span></button>
|
||||||
|
</div></div></div></template>
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* AudioSystem
|
* AudioSystem
|
||||||
|
* PopupMenu
|
||||||
* api
|
* api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ class DisplayAudio {
|
|||||||
this._autoPlayAudioDelay = 400;
|
this._autoPlayAudioDelay = 400;
|
||||||
this._eventListeners = new EventListenerCollection();
|
this._eventListeners = new EventListenerCollection();
|
||||||
this._cache = new Map();
|
this._cache = new Map();
|
||||||
|
this._menuContainer = document.querySelector('#popup-menus');
|
||||||
}
|
}
|
||||||
|
|
||||||
get autoPlayAudioDelay() {
|
get autoPlayAudioDelay() {
|
||||||
@ -58,6 +60,8 @@ class DisplayAudio {
|
|||||||
for (const button of entry.querySelectorAll('.action-play-audio')) {
|
for (const button of entry.querySelectorAll('.action-play-audio')) {
|
||||||
const expressionIndex = this._getAudioPlayButtonExpressionIndex(button);
|
const expressionIndex = this._getAudioPlayButtonExpressionIndex(button);
|
||||||
this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, definitionIndex, expressionIndex), false);
|
this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, definitionIndex, expressionIndex), false);
|
||||||
|
this._eventListeners.addEventListener(button, 'contextmenu', this._onAudioPlayButtonContextMenu.bind(this, definitionIndex, expressionIndex), false);
|
||||||
|
this._eventListeners.addEventListener(button, 'menuClose', this._onAudioPlayMenuCloseClick.bind(this, definitionIndex, expressionIndex), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +108,8 @@ class DisplayAudio {
|
|||||||
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
||||||
if (expressionReading === null) { return; }
|
if (expressionReading === null) { return; }
|
||||||
|
|
||||||
|
const buttons = this._getAudioPlayButtons(definitionIndex, expressionIndex);
|
||||||
|
|
||||||
const {expression, reading} = expressionReading;
|
const {expression, reading} = expressionReading;
|
||||||
const audioOptions = this._getAudioOptions();
|
const audioOptions = this._getAudioOptions();
|
||||||
const {textToSpeechVoice, customSourceUrl, volume} = audioOptions;
|
const {textToSpeechVoice, customSourceUrl, volume} = audioOptions;
|
||||||
@ -136,7 +142,7 @@ class DisplayAudio {
|
|||||||
|
|
||||||
// Update details
|
// Update details
|
||||||
const potentialAvailableAudioCount = this._getPotentialAvailableAudioCount(expression, reading);
|
const potentialAvailableAudioCount = this._getPotentialAvailableAudioCount(expression, reading);
|
||||||
for (const button of this._getAudioPlayButtons(definitionIndex, expressionIndex)) {
|
for (const button of buttons) {
|
||||||
const titleDefault = button.dataset.titleDefault || '';
|
const titleDefault = button.dataset.titleDefault || '';
|
||||||
button.title = `${titleDefault}\n${title}`;
|
button.title = `${titleDefault}\n${title}`;
|
||||||
this._updateAudioPlayButtonBadge(button, potentialAvailableAudioCount);
|
this._updateAudioPlayButtonBadge(button, potentialAvailableAudioCount);
|
||||||
@ -165,8 +171,38 @@ class DisplayAudio {
|
|||||||
|
|
||||||
_onAudioPlayButtonClick(definitionIndex, expressionIndex, e) {
|
_onAudioPlayButtonClick(definitionIndex, expressionIndex, e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (e.shiftKey) {
|
||||||
|
this._showAudioMenu(e.currentTarget, definitionIndex, expressionIndex);
|
||||||
|
} else {
|
||||||
this.playAudio(definitionIndex, expressionIndex);
|
this.playAudio(definitionIndex, expressionIndex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAudioPlayButtonContextMenu(definitionIndex, expressionIndex, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
this._showAudioMenu(e.currentTarget, definitionIndex, expressionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAudioPlayMenuCloseClick(definitionIndex, expressionIndex, e) {
|
||||||
|
const {detail: {action, item}} = e;
|
||||||
|
switch (action) {
|
||||||
|
case 'playAudioFromSource':
|
||||||
|
{
|
||||||
|
const {source, index} = item.dataset;
|
||||||
|
let sourceDetailsMap = null;
|
||||||
|
if (typeof index !== 'undefined') {
|
||||||
|
const index2 = Number.parseInt(index, 10);
|
||||||
|
sourceDetailsMap = new Map([
|
||||||
|
[source, {start: index2, end: index2 + 1}]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
this.playAudio(definitionIndex, expressionIndex, [source], sourceDetailsMap);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_getAudioPlayButtonExpressionIndex(button) {
|
_getAudioPlayButtonExpressionIndex(button) {
|
||||||
const expressionNode = button.closest('.term-expression');
|
const expressionNode = button.closest('.term-expression');
|
||||||
@ -360,4 +396,149 @@ class DisplayAudio {
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_showAudioMenu(button, definitionIndex, expressionIndex) {
|
||||||
|
const expressionReading = this._getExpressionAndReading(definitionIndex, expressionIndex);
|
||||||
|
if (expressionReading === null) { return; }
|
||||||
|
|
||||||
|
const {expression, reading} = expressionReading;
|
||||||
|
const popupMenu = this._createMenu(button, expression, reading);
|
||||||
|
popupMenu.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
_createMenu(button, expression, reading) {
|
||||||
|
// Options
|
||||||
|
const {sources, textToSpeechVoice, customSourceUrl} = this._getAudioOptions();
|
||||||
|
const sourceIndexMap = new Map();
|
||||||
|
for (let i = 0, ii = sources.length; i < ii; ++i) {
|
||||||
|
sourceIndexMap.set(sources[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create menu
|
||||||
|
const menuNode = this._display.displayGenerator.createPopupMenu('audio-button');
|
||||||
|
|
||||||
|
// Create menu item metadata
|
||||||
|
const menuItems = [];
|
||||||
|
const menuItemNodes = menuNode.querySelectorAll('.popup-menu-item');
|
||||||
|
for (let i = 0, ii = menuItemNodes.length; i < ii; ++i) {
|
||||||
|
const node = menuItemNodes[i];
|
||||||
|
const {source} = node.dataset;
|
||||||
|
let optionsIndex = sourceIndexMap.get(source);
|
||||||
|
if (typeof optionsIndex === 'undefined') { optionsIndex = null; }
|
||||||
|
menuItems.push({node, source, index: i, optionsIndex});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort according to source order in options
|
||||||
|
menuItems.sort((a, b) => {
|
||||||
|
const ai = a.optionsIndex;
|
||||||
|
const bi = b.optionsIndex;
|
||||||
|
if (ai !== null) {
|
||||||
|
if (bi !== null) {
|
||||||
|
const i = ai - bi;
|
||||||
|
if (i !== 0) { return i; }
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bi !== null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a.index - b.index;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up items based on cache data
|
||||||
|
const sourceMap = this._cache.get(this._getExpressionReadingKey(expression, reading));
|
||||||
|
const menuEntryMap = new Map();
|
||||||
|
let showIcons = false;
|
||||||
|
for (let i = 0, ii = menuItems.length; i < ii; ++i) {
|
||||||
|
const {node, source, optionsIndex} = menuItems[i];
|
||||||
|
const entries = this._getMenuItemEntries(node, sourceMap, source);
|
||||||
|
menuEntryMap.set(source, entries);
|
||||||
|
for (const {node: node2, valid, index} of entries) {
|
||||||
|
if (valid !== null) {
|
||||||
|
const icon = node2.querySelector('.popup-menu-item-icon');
|
||||||
|
icon.dataset.icon = valid ? 'checkmark' : 'cross';
|
||||||
|
showIcons = true;
|
||||||
|
}
|
||||||
|
if (index !== null) {
|
||||||
|
node2.dataset.index = `${index}`;
|
||||||
|
}
|
||||||
|
node2.dataset.valid = `${valid}`;
|
||||||
|
node2.dataset.sourceInOptions = `${optionsIndex !== null}`;
|
||||||
|
node2.style.order = `${i}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuNode.dataset.showIcons = `${showIcons}`;
|
||||||
|
|
||||||
|
// Hide options
|
||||||
|
if (textToSpeechVoice.length === 0) {
|
||||||
|
this._setMenuItemEntriesHidden(menuEntryMap, 'text-to-speech', true);
|
||||||
|
this._setMenuItemEntriesHidden(menuEntryMap, 'text-to-speech-reading', true);
|
||||||
|
}
|
||||||
|
if (customSourceUrl.length === 0) {
|
||||||
|
this._setMenuItemEntriesHidden(menuEntryMap, 'custom', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create popup menu
|
||||||
|
this._menuContainer.appendChild(menuNode);
|
||||||
|
return new PopupMenu(button, menuNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMenuItemEntries(node, sourceMap, source) {
|
||||||
|
const entries = [{node, valid: null, index: null}];
|
||||||
|
|
||||||
|
const nextNode = node.nextSibling;
|
||||||
|
|
||||||
|
if (typeof sourceMap === 'undefined') { return entries; }
|
||||||
|
|
||||||
|
const sourceInfo = sourceMap.get(source);
|
||||||
|
if (typeof sourceInfo === 'undefined') { return entries; }
|
||||||
|
|
||||||
|
const {infoList} = sourceInfo;
|
||||||
|
if (infoList === null) { return entries; }
|
||||||
|
|
||||||
|
if (infoList.length === 0) {
|
||||||
|
entries[0].valid = false;
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultLabel = node.querySelector('.popup-menu-item-label').textContent;
|
||||||
|
|
||||||
|
for (let i = 0, ii = infoList.length; i < ii; ++i) {
|
||||||
|
// Get/create entry
|
||||||
|
let entry;
|
||||||
|
if (i < entries.length) {
|
||||||
|
entry = entries[i];
|
||||||
|
} else {
|
||||||
|
const node2 = node.cloneNode(true);
|
||||||
|
nextNode.parentNode.insertBefore(node2, nextNode);
|
||||||
|
entry = {node: node2, valid: null, index: null};
|
||||||
|
entries.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry info
|
||||||
|
entry.index = i;
|
||||||
|
|
||||||
|
const {audio, audioResolved, title} = infoList[i];
|
||||||
|
if (audioResolved) { entry.valid = (audio !== null); }
|
||||||
|
|
||||||
|
const labelNode = entry.node.querySelector('.popup-menu-item-label');
|
||||||
|
let label = defaultLabel;
|
||||||
|
if (ii > 1) { label = `${label} ${i + 1}`; }
|
||||||
|
if (typeof title === 'string' && title.length > 0) { label += `: ${title}`; }
|
||||||
|
labelNode.textContent = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setMenuItemEntriesHidden(menuEntryMap, source, hidden) {
|
||||||
|
const entries = menuEntryMap.get(source);
|
||||||
|
if (typeof entries === 'undefined') { return; }
|
||||||
|
|
||||||
|
for (const {node} of entries) {
|
||||||
|
node.hidden = hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,6 +175,10 @@ class DisplayGenerator {
|
|||||||
return this._templates.instantiate('profile-list-item');
|
return this._templates.instantiate('profile-list-item');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createPopupMenu(name) {
|
||||||
|
return this._templates.instantiate(`${name}-popup-menu`);
|
||||||
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_createTermExpression(details) {
|
_createTermExpression(details) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* HotkeyHelpController
|
* HotkeyHelpController
|
||||||
* MediaLoader
|
* MediaLoader
|
||||||
* PopupFactory
|
* PopupFactory
|
||||||
|
* PopupMenu
|
||||||
* QueryParser
|
* QueryParser
|
||||||
* TextScanner
|
* TextScanner
|
||||||
* WindowScroll
|
* WindowScroll
|
||||||
@ -113,7 +114,7 @@ class Display extends EventDispatcher {
|
|||||||
this._displayAudio = new DisplayAudio(this);
|
this._displayAudio = new DisplayAudio(this);
|
||||||
|
|
||||||
this._hotkeyHandler.registerActions([
|
this._hotkeyHandler.registerActions([
|
||||||
['close', () => { this.close(); }],
|
['close', () => { this._onHotkeyClose(); }],
|
||||||
['nextEntry', () => { this._focusEntry(this._index + 1, true); }],
|
['nextEntry', () => { this._focusEntry(this._index + 1, true); }],
|
||||||
['nextEntry3', () => { this._focusEntry(this._index + 3, true); }],
|
['nextEntry3', () => { this._focusEntry(this._index + 3, true); }],
|
||||||
['previousEntry', () => { this._focusEntry(this._index - 1, true); }],
|
['previousEntry', () => { this._focusEntry(this._index - 1, true); }],
|
||||||
@ -517,6 +518,7 @@ class Display extends EventDispatcher {
|
|||||||
try {
|
try {
|
||||||
// Clear
|
// Clear
|
||||||
this._closePopups();
|
this._closePopups();
|
||||||
|
this._closeAllPopupMenus();
|
||||||
this._eventListeners.removeAllEventListeners();
|
this._eventListeners.removeAllEventListeners();
|
||||||
this._mediaLoader.unloadAll();
|
this._mediaLoader.unloadAll();
|
||||||
this._displayAudio.cleanupEntries();
|
this._displayAudio.cleanupEntries();
|
||||||
@ -1806,4 +1808,23 @@ class Display extends EventDispatcher {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onHotkeyClose() {
|
||||||
|
if (this._closeSinglePopupMenu()) { return; }
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
_closeAllPopupMenus() {
|
||||||
|
for (const popupMenu of PopupMenu.openMenus) {
|
||||||
|
popupMenu.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_closeSinglePopupMenu() {
|
||||||
|
for (const popupMenu of PopupMenu.openMenus) {
|
||||||
|
popupMenu.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,12 +76,16 @@ class PopupMenu extends EventDispatcher {
|
|||||||
|
|
||||||
_onMenuContainerClick(e) {
|
_onMenuContainerClick(e) {
|
||||||
if (e.currentTarget !== e.target) { return; }
|
if (e.currentTarget !== e.target) { return; }
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
this._close(null, 'outside', true);
|
this._close(null, 'outside', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMenuItemClick(e) {
|
_onMenuItemClick(e) {
|
||||||
const item = e.currentTarget;
|
const item = e.currentTarget;
|
||||||
if (item.disabled) { return; }
|
if (item.disabled) { return; }
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
this._close(item, 'item', true);
|
this._close(item, 'item', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user