Add custom context menu for bul edit actions

This commit is contained in:
artisticMink 2023-10-22 02:36:47 +02:00
parent 7d60d65d7e
commit 171c20ee16
3 changed files with 91 additions and 11 deletions

View File

@ -11,3 +11,34 @@
visibility: hidden; visibility: hidden;
height: 0 !important; height: 0 !important;
} }
#character_context_menu.hidden { display: none; }
#character_context_menu {
position: absolute;
padding: 3px;
z-index: 10000;
background-color: var(--SmartThemeUserMesBlurTintColor);
border: 1px solid var(--SmartThemeBorderColor);
border-radius: 10px;
}
#character_context_menu ul {
list-style-type: none;
padding: 0;
margin: 0;
}
#character_context_menu li {
padding: 10px;
border-radius: 10px;
cursor: pointer;
}
#character_context_menu .character_context_menu_separator {
height: 1px;
background-color: var(--SmartThemeBotMesBlurTintColor);
}
#character_context_menu li:hover {
background-color: var(--SmartThemeBotMesBlurTintColor);
}

View File

@ -100,6 +100,17 @@
<div id="bg_custom"></div> <div id="bg_custom"></div>
<div id="bg1"></div> <div id="bg1"></div>
<div id="character_context_menu" class="hidden">
<ul>
<li><a href="">Favorite</a></li>
<li class="character_context_menu_separator"></li>
<li><a href="">Duplicate</a></li>
<li><a href="">Export</a></li>
<li><a href="">To Persona</a></li>
<li><a href="">Delete</a></li>
</ul>
</div>
<!-- top bar central settings buttons --> <!-- top bar central settings buttons -->
<div id="top-bar"> <div id="top-bar">
</div> </div>
@ -4340,6 +4351,7 @@
</form> </form>
</div> </div>
</div> </div>
<div id="character_template" class="template_element"> <div id="character_template" class="template_element">
<div class="character_select flex-container wide100p alignitemsflexstart" chid="" id=""> <div class="character_select flex-container wide100p alignitemsflexstart" chid="" id="">
<div class="avatar" title=""> <div class="avatar" title="">

View File

@ -17,6 +17,8 @@ class State {
class CharacterGroupOverlay { class CharacterGroupOverlay {
static containerId = 'rm_print_characters_block'; static containerId = 'rm_print_characters_block';
static contextMenuClass = 'character_context_menu';
static characterClass = 'character_select';
static selectModeClass = 'group_overlay_mode_select'; static selectModeClass = 'group_overlay_mode_select';
static selectedClass = 'character_selected'; static selectedClass = 'character_selected';
@ -79,12 +81,12 @@ class CharacterGroupOverlay {
*/ */
onPageLoad = () => { onPageLoad = () => {
let touchState = false; let touchState = false;
const grid = document.getElementById('rm_print_characters_block'); const grid = document.getElementById(CharacterGroupOverlay.containerId);
const sortable = new Sortable(grid, { const sortable = new Sortable(grid, {
group: 'shared', group: 'shared',
animation: 150, animation: 150,
sort:false, sort: false,
handle: '.character_select', handle: '.character_select',
onEnd: (evt) => { onEnd: (evt) => {
if (evt.from !== evt.to) { if (evt.from !== evt.to) {
@ -93,18 +95,36 @@ class CharacterGroupOverlay {
} }
}); });
const elements = [...document.getElementsByClassName('character_select')]; const elements = [...document.getElementsByClassName(CharacterGroupOverlay.characterClass)];
elements.forEach(element => element.addEventListener('touchstart', this.handleHold)); elements.forEach(element => element.addEventListener('touchstart', this.handleHold));
elements.forEach(element => element.addEventListener('mousedown', this.handleHold)); elements.forEach(element => element.addEventListener('mousedown', this.handleHold));
elements.forEach(element => element.addEventListener('touchend', this._handleLongPressEnd)); elements.forEach(element => element.addEventListener('touchend', this.handleLongPressEnd));
elements.forEach(element => element.addEventListener('mouseup', this._handleLongPressEnd)); elements.forEach(element => element.addEventListener('mouseup', this.handleLongPressEnd));
elements.forEach(element => element.addEventListener('dragend', this._handleLongPressEnd)); elements.forEach(element => element.addEventListener('dragend', this.handleLongPressEnd));
grid.addEventListener('click', this.handleCancelClick); grid.addEventListener('click', this.handleCancelClick);
} }
/**
* Block the browsers native context menu and
* set a click event to hide the custom context menu.
*/
enableContextMenu = () => {
document.addEventListener('contextmenu', this.handleContextMenuShow);
document.addEventListener('click', this.handleContextMenuHide);
}
/**
* Remove event listeners, allowing the native browser context
* menu to be opened.
*/
disableContextMenu = () => {
document.removeEventListener('contextmenu', this.handleContextMenuShow);
document.removeEventListener('click', this.handleContextMenuHide);
}
handleHold = (event) => { handleHold = (event) => {
this.isLongPress = true; this.isLongPress = true;
setTimeout(() => { setTimeout(() => {
@ -114,7 +134,7 @@ class CharacterGroupOverlay {
}, 3000); }, 3000);
} }
_handleLongPressEnd = () => { handleLongPressEnd = () => {
this.isLongPress = false; this.isLongPress = false;
} }
@ -126,16 +146,17 @@ class CharacterGroupOverlay {
switch (this.state) { switch (this.state) {
case State.browse: case State.browse:
this.container.classList.remove(CharacterGroupOverlay.selectModeClass); this.container.classList.remove(CharacterGroupOverlay.selectModeClass);
[...this.container.getElementsByClassName('character_select')] [...this.container.getElementsByClassName(CharacterGroupOverlay.characterClass)]
.forEach(element => element.removeEventListener('click', this.toggleCharacterSelected)); .forEach(element => element.removeEventListener('click', this.toggleCharacterSelected));
this.longPressEndCallbacks.forEach(callback => callback()); this.longPressEndCallbacks.forEach(callback => callback());
this.clearSelectedCharacters(); this.clearSelectedCharacters();
this.disableContextMenu();
break; break;
case State.select: case State.select:
this.container.classList.add(CharacterGroupOverlay.selectModeClass); this.container.classList.add(CharacterGroupOverlay.selectModeClass);
[...this.container.getElementsByClassName('character_select')] [...this.container.getElementsByClassName(CharacterGroupOverlay.characterClass)]
.forEach(element => element.addEventListener('click', this.toggleCharacterSelected)); .forEach(element => element.addEventListener('click', this.toggleCharacterSelected));
this.clearSelectedCharacters(); this.enableContextMenu();
} }
} }
@ -154,7 +175,23 @@ class CharacterGroupOverlay {
character.classList.add(CharacterGroupOverlay.selectedClass); character.classList.add(CharacterGroupOverlay.selectedClass);
this.selectCharacter(characterId); this.selectCharacter(characterId);
} }
}
handleContextMenuShow = (event) => {
event.preventDefault();
document.getElementById(CharacterGroupOverlay.containerId).style.pointerEvents = 'none';
let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuClass);
contextMenu.style.top = `${event.clientY}px`;
contextMenu.style.left = `${event.clientX}px`;
contextMenu.classList.remove('hidden');
}
handleContextMenuHide = (event) => {
document.getElementById(CharacterGroupOverlay.containerId).style.pointerEvents = '';
let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuClass);
if (false === contextMenu.contains(event.target)) {
contextMenu.classList.add('hidden');
}
} }
addLongPressEndCallback = callback => this.longPressEndCallbacks.push(callback); addLongPressEndCallback = callback => this.longPressEndCallbacks.push(callback);
@ -164,7 +201,7 @@ class CharacterGroupOverlay {
dismissCharacter = characterId => this.#selectedCharacters = this.selectedCharacters.filter(item => String(characterId) !== item); dismissCharacter = characterId => this.#selectedCharacters = this.selectedCharacters.filter(item => String(characterId) !== item);
clearSelectedCharacters = () => { clearSelectedCharacters = () => {
this.selectedCharacters.forEach(characterId => document.querySelector('.character_select[chid="'+characterId+'"]')?.classList.remove(CharacterGroupOverlay.selectedClass)) this.selectedCharacters.forEach(characterId => document.querySelector('.character_select[chid="' + characterId + '"]')?.classList.remove(CharacterGroupOverlay.selectedClass))
this.selectedCharacters.length = 0; this.selectedCharacters.length = 0;
} }
} }