mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2024-12-12 01:17:39 +01:00
Add custom context menu for bul edit actions
This commit is contained in:
parent
7d60d65d7e
commit
171c20ee16
@ -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);
|
||||||
|
}
|
||||||
|
@ -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="">
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user