mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add pagination for characters list view
This commit is contained in:
@@ -13,11 +13,13 @@ import {
|
||||
menu_type,
|
||||
max_context,
|
||||
saveSettingsDebounced,
|
||||
eventSource,
|
||||
active_group,
|
||||
active_character,
|
||||
setActiveGroup,
|
||||
setActiveCharacter,
|
||||
getEntitiesList,
|
||||
getThumbnailUrl,
|
||||
selectCharacterById,
|
||||
} from "../script.js";
|
||||
|
||||
import {
|
||||
@@ -348,12 +350,13 @@ async function RA_autoloadchat() {
|
||||
// active character is the name, we should look it up in the character list and get the id
|
||||
let active_character_id = Object.keys(characters).find(key => characters[key].avatar === active_character);
|
||||
|
||||
var charToAutoLoad = document.getElementById('CharID' + active_character_id);
|
||||
let groupToAutoLoad = document.querySelector(`.group_select[grid="${active_group}"]`);
|
||||
if (charToAutoLoad != null) {
|
||||
$(charToAutoLoad).click();
|
||||
if (active_character_id !== null) {
|
||||
selectCharacterById(String(active_character_id));
|
||||
}
|
||||
else if (groupToAutoLoad != null) {
|
||||
|
||||
let groupToAutoLoad = document.querySelector(`.group_select[grid="${active_group}"]`);
|
||||
|
||||
if (groupToAutoLoad != null) {
|
||||
$(groupToAutoLoad).click();
|
||||
}
|
||||
|
||||
@@ -362,53 +365,60 @@ async function RA_autoloadchat() {
|
||||
}
|
||||
|
||||
export async function favsToHotswap() {
|
||||
const selector = ['#rm_print_characters_block .character_select', '#rm_print_characters_block .group_select'].join(',');
|
||||
const entities = getEntitiesList({ doFilter: false });
|
||||
const container = $('#right-nav-panel .hotswap');
|
||||
const template = $('#hotswap_template .hotswapAvatar');
|
||||
container.empty();
|
||||
const maxCount = 6;
|
||||
let count = 0;
|
||||
|
||||
$(selector).sort(sortByCssOrder).each(function () {
|
||||
if ($(this).hasClass('is_fav') && count < maxCount) {
|
||||
const isCharacter = $(this).hasClass('character_select');
|
||||
const isGroup = $(this).hasClass('group_select');
|
||||
const grid = Number($(this).attr('grid'));
|
||||
const chid = Number($(this).attr('chid'));
|
||||
let thisHotSwapSlot = template.clone();
|
||||
thisHotSwapSlot.toggleClass('character_select', isCharacter);
|
||||
thisHotSwapSlot.toggleClass('group_select', isGroup);
|
||||
thisHotSwapSlot.attr('grid', isGroup ? grid : '');
|
||||
thisHotSwapSlot.attr('chid', isCharacter ? chid : '');
|
||||
thisHotSwapSlot.data('id', isGroup ? grid : chid);
|
||||
thisHotSwapSlot.attr('title', '');
|
||||
|
||||
if (isGroup) {
|
||||
const group = groups.find(x => x.id === grid);
|
||||
const avatar = getGroupAvatar(group);
|
||||
$(thisHotSwapSlot).find('img').replaceWith(avatar);
|
||||
}
|
||||
|
||||
if (isCharacter) {
|
||||
const avatarUrl = $(this).find('img').attr('src');
|
||||
$(thisHotSwapSlot).find('img').attr('src', avatarUrl);
|
||||
}
|
||||
|
||||
$(thisHotSwapSlot).css('cursor', 'pointer');
|
||||
container.append(thisHotSwapSlot);
|
||||
count++;
|
||||
for (const entity of entities) {
|
||||
if (count >= maxCount) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//console.log('about to check for leftover selectors...')
|
||||
const isFavorite = entity.item.fav || entity.item.fav == 'true';
|
||||
|
||||
if (!isFavorite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isCharacter = entity.type === 'character';
|
||||
const isGroup = entity.type === 'group';
|
||||
|
||||
const grid = isGroup ? entity.id : '';
|
||||
const chid = isCharacter ? entity.id : '';
|
||||
|
||||
let slot = template.clone();
|
||||
slot.toggleClass('character_select', isCharacter);
|
||||
slot.toggleClass('group_select', isGroup);
|
||||
slot.attr('grid', isGroup ? grid : '');
|
||||
slot.attr('chid', isCharacter ? chid : '');
|
||||
slot.data('id', isGroup ? grid : chid);
|
||||
slot.attr('title', '');
|
||||
|
||||
if (isGroup) {
|
||||
const group = groups.find(x => x.id === grid);
|
||||
const avatar = getGroupAvatar(group);
|
||||
$(slot).find('img').replaceWith(avatar);
|
||||
}
|
||||
|
||||
if (isCharacter) {
|
||||
const avatarUrl = getThumbnailUrl('avatar', entity.item.avatar);
|
||||
$(slot).find('img').attr('src', avatarUrl);
|
||||
}
|
||||
|
||||
$(slot).css('cursor', 'pointer');
|
||||
container.append(slot);
|
||||
count++;
|
||||
}
|
||||
|
||||
// there are 6 slots in total,
|
||||
if (count < maxCount) { //if any are left over
|
||||
let leftOverSlots = maxCount - count;
|
||||
for (let i = 1; i <= leftOverSlots; i++) {
|
||||
container.append(template.clone());
|
||||
}
|
||||
} else {
|
||||
//console.log(`count was ${count} so no need to knock off any selectors!`);
|
||||
}
|
||||
}
|
||||
|
||||
|
129
public/scripts/filters.js
Normal file
129
public/scripts/filters.js
Normal file
@@ -0,0 +1,129 @@
|
||||
import { fuzzySearchCharacters, fuzzySearchGroups, power_user } from "./power-user.js";
|
||||
import { tag_map } from "./tags.js";
|
||||
|
||||
export const FILTER_TYPES = {
|
||||
SEARCH: 'search',
|
||||
TAG: 'tag',
|
||||
FAV: 'fav',
|
||||
GROUP: 'group',
|
||||
};
|
||||
|
||||
export class FilterHelper {
|
||||
constructor(onDataChanged) {
|
||||
this.onDataChanged = onDataChanged;
|
||||
}
|
||||
|
||||
filterFunctions = {
|
||||
[FILTER_TYPES.SEARCH]: this.searchFilter.bind(this),
|
||||
[FILTER_TYPES.GROUP]: this.groupFilter.bind(this),
|
||||
[FILTER_TYPES.FAV]: this.favFilter.bind(this),
|
||||
[FILTER_TYPES.TAG]: this.tagFilter.bind(this),
|
||||
}
|
||||
|
||||
filterData = {
|
||||
[FILTER_TYPES.SEARCH]: '',
|
||||
[FILTER_TYPES.GROUP]: false,
|
||||
[FILTER_TYPES.FAV]: false,
|
||||
[FILTER_TYPES.TAG]: { excluded: [], selected: [] },
|
||||
}
|
||||
|
||||
tagFilter(data) {
|
||||
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
||||
const { selected, excluded } = this.filterData[FILTER_TYPES.TAG];
|
||||
|
||||
if (!selected.length && !excluded.length) {
|
||||
return data;
|
||||
}
|
||||
|
||||
function isElementTagged(entity, tagId) {
|
||||
const isCharacter = entity.type === 'character';
|
||||
const lookupValue = isCharacter ? entity.item.avatar : String(entity.id);
|
||||
const isTagged = Array.isArray(tag_map[lookupValue]) && tag_map[lookupValue].includes(tagId);
|
||||
return isTagged;
|
||||
}
|
||||
|
||||
function getIsTagged(entity) {
|
||||
const tagFlags = selected.map(tagId => isElementTagged(entity, tagId));
|
||||
const trueFlags = tagFlags.filter(x => x);
|
||||
const isTagged = TAG_LOGIC_AND ? tagFlags.length === trueFlags.length : trueFlags.length > 0;
|
||||
|
||||
const excludedTagFlags = excluded.map(tagId => isElementTagged(entity, tagId));
|
||||
const isExcluded = excludedTagFlags.includes(true);
|
||||
|
||||
if (isExcluded) {
|
||||
return false;
|
||||
} else if (selected.length > 0 && !isTagged) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return data.filter(entity => getIsTagged(entity));
|
||||
}
|
||||
|
||||
favFilter(data) {
|
||||
if (!this.filterData[FILTER_TYPES.FAV]) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return data.filter(entity => entity.item.fav || entity.item.fav == "true");
|
||||
}
|
||||
|
||||
groupFilter(data) {
|
||||
if (!this.filterData[FILTER_TYPES.GROUP]) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return data.filter(entity => entity.type === 'group');
|
||||
}
|
||||
|
||||
searchFilter(data) {
|
||||
if (!this.filterData[FILTER_TYPES.SEARCH]) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const searchValue = this.filterData[FILTER_TYPES.SEARCH].trim().toLowerCase();
|
||||
const fuzzySearchCharactersResults = power_user.fuzzy_search ? fuzzySearchCharacters(searchValue) : [];
|
||||
const fuzzySearchGroupsResults = power_user.fuzzy_search ? fuzzySearchGroups(searchValue) : [];
|
||||
|
||||
function getIsValidSearch(entity) {
|
||||
const isGroup = entity.type === 'group';
|
||||
const isCharacter = entity.type === 'character';
|
||||
|
||||
if (power_user.fuzzy_search) {
|
||||
if (isCharacter) {
|
||||
return fuzzySearchCharactersResults.includes(parseInt(entity.id));
|
||||
} else if (isGroup) {
|
||||
return fuzzySearchGroupsResults.includes(String(entity.id));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return entity.item?.name?.toLowerCase()?.includes(searchValue) || false;
|
||||
}
|
||||
}
|
||||
|
||||
return data.filter(entity => getIsValidSearch(entity));
|
||||
}
|
||||
|
||||
setFilterData(filterType, data) {
|
||||
const oldData = this.filterData[filterType];
|
||||
this.filterData[filterType] = data;
|
||||
|
||||
// only trigger a data change if the data actually changed
|
||||
if (JSON.stringify(oldData) !== JSON.stringify(data)) {
|
||||
this.onDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
getFilterData(filterType) {
|
||||
return this.filterData[filterType];
|
||||
}
|
||||
|
||||
applyFilters(data) {
|
||||
return Object.values(this.filterFunctions)
|
||||
.reduce((data, fn) => fn(data), data);
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@ import {
|
||||
extractAllWords,
|
||||
} from './utils.js';
|
||||
import { RA_CountCharTokens, humanizedDateTime, dragElement } from "./RossAscends-mods.js";
|
||||
import { sortCharactersList, sortGroupMembers, loadMovingUIState } from './power-user.js';
|
||||
import { sortGroupMembers, loadMovingUIState } from './power-user.js';
|
||||
|
||||
import {
|
||||
chat,
|
||||
@@ -63,6 +63,7 @@ import {
|
||||
getCropPopup,
|
||||
} from "../script.js";
|
||||
import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect, tag_map } from './tags.js';
|
||||
import { FilterHelper } from './filters.js';
|
||||
|
||||
export {
|
||||
selected_group,
|
||||
@@ -75,7 +76,6 @@ export {
|
||||
deleteGroup,
|
||||
getGroupAvatar,
|
||||
getGroups,
|
||||
printGroups,
|
||||
regenerateGroup,
|
||||
resetSelectedGroup,
|
||||
select_group_chats,
|
||||
@@ -94,9 +94,15 @@ export const group_activation_strategy = {
|
||||
LIST: 1,
|
||||
};
|
||||
|
||||
export const groupCandidatesFilter = new FilterHelper(debounce(printGroupCandidates, 100));
|
||||
const groupAutoModeInterval = setInterval(groupChatAutoModeWorker, 5000);
|
||||
const saveGroupDebounced = debounce(async (group) => await _save(group), 500);
|
||||
|
||||
function printGroupCandidates(fullRefresh = false) {
|
||||
toastr.info('Group candidates tags filter is temporarily unavailable.');
|
||||
console.log('TODO: implement printGroupCandidates');
|
||||
}
|
||||
|
||||
async function _save(group, reload = true) {
|
||||
await fetch("/editgroup", {
|
||||
method: "POST",
|
||||
@@ -228,7 +234,6 @@ async function saveGroupChat(groupId, shouldSaveGroup) {
|
||||
if (shouldSaveGroup && response.ok) {
|
||||
await editGroup(groupId);
|
||||
}
|
||||
sortCharactersList();
|
||||
}
|
||||
|
||||
export async function renameGroupMember(oldAvatar, newAvatar, newName) {
|
||||
@@ -330,8 +335,7 @@ async function getGroups() {
|
||||
}
|
||||
}
|
||||
|
||||
function printGroups() {
|
||||
for (let group of groups) {
|
||||
export function getGroupBlock(group) {
|
||||
const template = $("#group_list_template .group_select").clone();
|
||||
template.data("id", group.id);
|
||||
template.attr("grid", group.id);
|
||||
@@ -345,10 +349,14 @@ function printGroups() {
|
||||
const tagsElement = template.find('.tags');
|
||||
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
||||
|
||||
$("#rm_print_characters_block").prepend(template);
|
||||
updateGroupAvatar(group);
|
||||
}
|
||||
const avatar = getGroupAvatar(group);
|
||||
if (avatar) {
|
||||
$(template).find(".avatar").replaceWith(avatar);
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function updateGroupAvatar(group) {
|
||||
$("#rm_print_characters_block .group_select").each(function () {
|
||||
if ($(this).data("id") == group.id) {
|
||||
@@ -1353,7 +1361,6 @@ export async function openGroupChat(groupId, chatId) {
|
||||
|
||||
await editGroup(groupId, true);
|
||||
await getGroupChat(groupId);
|
||||
sortCharactersList();
|
||||
}
|
||||
|
||||
export async function renameGroupChat(groupId, oldChatId, newChatId) {
|
||||
|
1190
public/scripts/pagination.js
Normal file
1190
public/scripts/pagination.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,6 @@ import {
|
||||
reloadCurrentChat,
|
||||
getRequestHeaders,
|
||||
substituteParams,
|
||||
updateVisibleDivs,
|
||||
eventSource,
|
||||
event_types,
|
||||
getCurrentChatId,
|
||||
@@ -18,7 +17,7 @@ import {
|
||||
setCharacterId,
|
||||
setEditedMessageId
|
||||
} from "../script.js";
|
||||
import { favsToHotswap, isMobile, initMovingUI } from "./RossAscends-mods.js";
|
||||
import { isMobile, initMovingUI } from "./RossAscends-mods.js";
|
||||
import {
|
||||
groups,
|
||||
resetSelectedGroup,
|
||||
@@ -35,7 +34,7 @@ export {
|
||||
collapseNewlines,
|
||||
playMessageSound,
|
||||
sortGroupMembers,
|
||||
sortCharactersList,
|
||||
sortEntitiesList,
|
||||
fixMarkdown,
|
||||
power_user,
|
||||
pygmalion_options,
|
||||
@@ -803,7 +802,6 @@ function loadPowerUserSettings(settings, data) {
|
||||
|
||||
|
||||
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
|
||||
sortCharactersList();
|
||||
reloadMarkdownProcessor(power_user.render_formulas);
|
||||
loadInstructMode();
|
||||
loadContextSettings();
|
||||
@@ -812,7 +810,6 @@ function loadPowerUserSettings(settings, data) {
|
||||
switchSpoilerMode();
|
||||
loadMovingUIState();
|
||||
loadCharListState();
|
||||
|
||||
}
|
||||
|
||||
async function loadCharListState() {
|
||||
@@ -1129,32 +1126,12 @@ const compareFunc = (first, second) => {
|
||||
}
|
||||
};
|
||||
|
||||
function sortCharactersList() {
|
||||
const arr1 = groups.map(x => ({
|
||||
item: x,
|
||||
id: x.id,
|
||||
selector: '.group_select',
|
||||
attribute: 'grid',
|
||||
}))
|
||||
const arr2 = characters.map((x, index) => ({
|
||||
item: x,
|
||||
id: index,
|
||||
selector: '.character_select',
|
||||
attribute: 'chid',
|
||||
}));
|
||||
|
||||
const array = [...arr1, ...arr2];
|
||||
|
||||
if (power_user.sort_field == undefined || array.length === 0) {
|
||||
function sortEntitiesList(entities) {
|
||||
if (power_user.sort_field == undefined || entities.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let orderedList = array.slice().sort((a, b) => sortFunc(a.item, b.item));
|
||||
|
||||
for (const item of array) {
|
||||
$(`${item.selector}[${item.attribute}="${item.id}"]`).css({ 'order': orderedList.indexOf(item) });
|
||||
}
|
||||
updateVisibleDivs('#rm_print_characters_block', true);
|
||||
entities.sort((a, b) => sortFunc(a.item, b.item));
|
||||
}
|
||||
|
||||
function sortGroupMembers(selector) {
|
||||
@@ -1900,6 +1877,7 @@ $(document).ready(() => {
|
||||
power_user.never_resize_avatars = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#show_card_avatar_urls").on('input', function () {
|
||||
power_user.show_card_avatar_urls = !!$(this).prop('checked');
|
||||
printCharacters();
|
||||
@@ -1925,8 +1903,7 @@ $(document).ready(() => {
|
||||
power_user.sort_field = $(this).find(":selected").data('field');
|
||||
power_user.sort_order = $(this).find(":selected").data('order');
|
||||
power_user.sort_rule = $(this).find(":selected").data('rule');
|
||||
sortCharactersList();
|
||||
favsToHotswap();
|
||||
printCharacters();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
@@ -2038,12 +2015,6 @@ $(document).ready(() => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
/* $("#removeXML").on("input", function () {
|
||||
power_user.removeXML = !!$(this).prop('checked');
|
||||
reloadCurrentChat();
|
||||
saveSettingsDebounced();
|
||||
}); */
|
||||
|
||||
$("#token_padding").on("input", function () {
|
||||
power_user.token_padding = Number($(this).val());
|
||||
saveSettingsDebounced();
|
||||
|
@@ -4,12 +4,12 @@ import {
|
||||
this_chid,
|
||||
callPopup,
|
||||
menu_type,
|
||||
updateVisibleDivs,
|
||||
getCharacters,
|
||||
updateCharacterCount,
|
||||
entitiesFilter,
|
||||
} from "../script.js";
|
||||
import { FILTER_TYPES } from "./filters.js";
|
||||
|
||||
import { selected_group } from "./group-chats.js";
|
||||
import { groupCandidatesFilter, selected_group } from "./group-chats.js";
|
||||
import { uuidv4 } from "./utils.js";
|
||||
|
||||
export {
|
||||
@@ -17,7 +17,6 @@ export {
|
||||
tag_map,
|
||||
loadTagsSettings,
|
||||
printTagFilters,
|
||||
isElementTagged,
|
||||
getTagsList,
|
||||
appendTagToList,
|
||||
createTagMapFromList,
|
||||
@@ -26,18 +25,11 @@ export {
|
||||
};
|
||||
|
||||
const random_id = () => uuidv4();
|
||||
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
||||
const CHARACTER_SELECTOR = '#rm_print_characters_block > div';
|
||||
const GROUP_MEMBER_SELECTOR = '#rm_group_add_members > div';
|
||||
const CHARACTER_FILTER_SELECTOR = '#rm_characters_block .rm_tag_filter';
|
||||
const GROUP_FILTER_SELECTOR = '#rm_group_chats_block .rm_tag_filter';
|
||||
|
||||
function getCharacterSelector(listSelector) {
|
||||
if ($(listSelector).is(GROUP_FILTER_SELECTOR)) {
|
||||
return GROUP_MEMBER_SELECTOR;
|
||||
}
|
||||
|
||||
return CHARACTER_SELECTOR;
|
||||
function getFilterHelper(listSelector) {
|
||||
return $(listSelector).is(GROUP_FILTER_SELECTOR) ? groupCandidatesFilter : entitiesFilter;
|
||||
}
|
||||
|
||||
export const tag_filter_types = {
|
||||
@@ -68,37 +60,20 @@ const DEFAULT_TAGS = [
|
||||
let tags = [];
|
||||
let tag_map = {};
|
||||
|
||||
function applyFavFilter(characterSelector) {
|
||||
function applyFavFilter(filterHelper) {
|
||||
const isSelected = $(this).hasClass('selected');
|
||||
const displayFavoritesOnly = !isSelected;
|
||||
|
||||
$(this).toggleClass('selected', displayFavoritesOnly);
|
||||
$(characterSelector).removeClass('hiddenByFav');
|
||||
|
||||
$(characterSelector).each(function () {
|
||||
if (displayFavoritesOnly) {
|
||||
if ($(this).find(".ch_fav").length !== 0) {
|
||||
const shouldBeDisplayed = $(this).find(".ch_fav").val().toLowerCase().includes(true);
|
||||
$(this).toggleClass('hiddenByFav', !shouldBeDisplayed);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
updateCharacterCount(characterSelector);
|
||||
updateVisibleDivs('#rm_print_characters_block', true);
|
||||
filterHelper.setFilterData(FILTER_TYPES.FAV, displayFavoritesOnly);
|
||||
}
|
||||
|
||||
function filterByGroups(characterSelector) {
|
||||
function filterByGroups(filterHelper) {
|
||||
const isSelected = $(this).hasClass('selected');
|
||||
const displayGroupsOnly = !isSelected;
|
||||
$(this).toggleClass('selected', displayGroupsOnly);
|
||||
$(characterSelector).removeClass('hiddenByGroup');
|
||||
|
||||
$(characterSelector).each((_, element) => {
|
||||
$(element).toggleClass('hiddenByGroup', displayGroupsOnly && !$(element).hasClass('group_select'));
|
||||
});
|
||||
updateCharacterCount(characterSelector);
|
||||
updateVisibleDivs('#rm_print_characters_block', true);
|
||||
filterHelper.setFilterData(FILTER_TYPES.GROUP, displayGroupsOnly);
|
||||
}
|
||||
|
||||
function loadTagsSettings(settings) {
|
||||
@@ -291,7 +266,6 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
||||
return;
|
||||
}
|
||||
|
||||
const characterSelector = getCharacterSelector($(listElement));
|
||||
|
||||
let tagElement = $('#tag_template .tag').clone();
|
||||
tagElement.attr('id', tag.id);
|
||||
@@ -316,11 +290,12 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
||||
}
|
||||
|
||||
if (selectable) {
|
||||
tagElement.on('click', () => onTagFilterClick.bind(tagElement)(listElement, characterSelector));
|
||||
tagElement.on('click', () => onTagFilterClick.bind(tagElement)(listElement));
|
||||
}
|
||||
|
||||
if (action) {
|
||||
tagElement.on('click', () => action.bind(tagElement)(characterSelector));
|
||||
const filter = getFilterHelper($(listElement));
|
||||
tagElement.on('click', () => action.bind(tagElement)(filter));
|
||||
tagElement.addClass('actionable');
|
||||
}
|
||||
if (action && tag.id === 2) {
|
||||
@@ -330,7 +305,7 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
|
||||
$(listElement).append(tagElement);
|
||||
}
|
||||
|
||||
function onTagFilterClick(listElement, characterSelector) {
|
||||
function onTagFilterClick(listElement) {
|
||||
let excludeTag;
|
||||
if ($(this).hasClass('selected')) {
|
||||
$(this).removeClass('selected');
|
||||
@@ -356,44 +331,10 @@ function onTagFilterClick(listElement, characterSelector) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Overhaul this somehow to use settings tag IDs instead
|
||||
const tagIds = [...($(listElement).find(".tag.selected:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
||||
const excludedTagIds = [...($(listElement).find(".tag.excluded:not(.actionable)").map((_, el) => $(el).attr("id")))];
|
||||
$(characterSelector).each((_, element) => applyFilterToElement(tagIds, excludedTagIds, element));
|
||||
updateCharacterCount(characterSelector);
|
||||
updateVisibleDivs('#rm_print_characters_block', true);
|
||||
}
|
||||
|
||||
function applyFilterToElement(tagIds, excludedTagIds, element) {
|
||||
const tagFlags = tagIds.map(tagId => isElementTagged(element, tagId));
|
||||
const trueFlags = tagFlags.filter(x => x);
|
||||
const isTagged = TAG_LOGIC_AND ? tagFlags.length === trueFlags.length : trueFlags.length > 0;
|
||||
|
||||
const excludedTagFlags = excludedTagIds.map(tagId => isElementTagged(element, tagId));
|
||||
const isExcluded = excludedTagFlags.includes(true);
|
||||
|
||||
if (isExcluded) {
|
||||
$(element).addClass('hiddenByTag');
|
||||
} else if (tagIds.length > 0 && !isTagged) {
|
||||
$(element).addClass('hiddenByTag');
|
||||
} else {
|
||||
$(element).removeClass('hiddenByTag');
|
||||
}
|
||||
}
|
||||
|
||||
function isElementTagged(element, tagId) {
|
||||
const isGroup = $(element).hasClass('group_select');
|
||||
const isCharacter = $(element).hasClass('character_select') || $(element).hasClass('group_member');
|
||||
const idAttr = isGroup ? 'grid' : 'chid';
|
||||
const elementId = $(element).attr(idAttr);
|
||||
const lookupValue = isCharacter ? characters[elementId].avatar : elementId;
|
||||
const isTagged = Array.isArray(tag_map[lookupValue]) && tag_map[lookupValue].includes(tagId);
|
||||
return isTagged;
|
||||
}
|
||||
|
||||
function clearTagsFilter(characterSelector) {
|
||||
$('.rm_tag_filter .tag').removeClass('selected');
|
||||
$(characterSelector).removeClass('hiddenByTag');
|
||||
const filterHelper = getFilterHelper($(listElement));
|
||||
filterHelper.setFilterData(FILTER_TYPES.TAG, { excluded: excludedTagIds, selected: tagIds });
|
||||
}
|
||||
|
||||
function printTagFilters(type = tag_filter_types.character) {
|
||||
|
Reference in New Issue
Block a user