Tag Folders: Clear all filters button

- Add "clear all filters" button for tag and search filters
- Resize back button to take less space
- Fix char grid display
This commit is contained in:
Wolfsblvt 2024-03-07 04:26:33 +01:00
parent fb97f563b7
commit 9f42cafc39
5 changed files with 83 additions and 22 deletions

View File

@ -68,6 +68,11 @@
align-items: center; align-items: center;
} }
.tag.actionable.clearAllFilters {
border: 0;
background: none;
}
.tagListHint { .tagListHint {
align-self: center; align-self: center;
display: flex; display: flex;
@ -217,6 +222,10 @@
opacity: 1; opacity: 1;
} }
.rm_tag_bogus_drilldown {
height: calc(var(--mainFontSize)* 2 - 2);
}
.rm_tag_bogus_drilldown .tag:not(:first-child) { .rm_tag_bogus_drilldown .tag:not(:first-child) {
position: relative; position: relative;
margin-left: calc(var(--mainFontSize) * 2); margin-left: calc(var(--mainFontSize) * 2);
@ -238,3 +247,12 @@
opacity: 1; opacity: 1;
} }
.bogus_folder_select_back .avatar {
display: none;
}
.bogus_folder_select_back .bogus_folder_back_placeholder {
min-height: calc(var(--mainFontSize)*2);
width: var(--avatar-base-width);
justify-content: center;
}

View File

@ -96,14 +96,18 @@ body.charListGrid #rm_print_characters_block .group_select .group_name_block {
body.charListGrid #rm_print_characters_block .ch_description, body.charListGrid #rm_print_characters_block .ch_description,
body.charListGrid #rm_print_characters_block .tags_inline, body.charListGrid #rm_print_characters_block .tags_inline,
body.charListGrid #rm_print_characters_block .character_version, body.charListGrid #rm_print_characters_block .character_version,
body.charListGrid #rm_print_characters_block .bogus_folder_unit,
body.charListGrid #rm_print_characters_block .group_select_unit,
body.charListGrid #rm_print_characters_block .group_select_block_list, body.charListGrid #rm_print_characters_block .group_select_block_list,
body.charListGrid #rm_print_characters_block .ch_avatar_url, body.charListGrid #rm_print_characters_block .ch_avatar_url,
#user_avatar_block.gridView .avatar-container .ch_description { body.charListGrid #rm_print_characters_block .character_name_block_sub_line,
#user_avatar_block.gridView .avatar-container .ch_description,
body.charListGrid #rm_print_characters_block .bogus_folder_select_back .bogus_folder_back_placeholder {
display: none; display: none;
} }
body.charListGrid #rm_print_characters_block .bogus_folder_select_back .avatar {
display: flex;
}
/*big avatars mode page-wide changes*/ /*big avatars mode page-wide changes*/
body.big-avatars .character_select .avatar, body.big-avatars .character_select .avatar,

View File

@ -5026,10 +5026,13 @@
</div> </div>
</div> </div>
<div id="bogus_folder_back_template" class="template_element"> <div id="bogus_folder_back_template" class="template_element">
<div class="bogus_folder_select flex-container wide100p alignitemsflexstart" id="BogusFolderBack" tagid="back"> <div class="bogus_folder_select bogus_folder_select_back flex-container wide100p alignitemsflexstart" id="BogusFolderBack" tagid="back">
<div class="avatar flex alignitemscenter textAlignCenter"> <div class="avatar flex alignitemscenter textAlignCenter">
<i class="bogus_folder_icon fa-solid fa-xl fa-right-from-bracket fa-flip-horizontal"></i> <i class="bogus_folder_icon fa-solid fa-xl fa-right-from-bracket fa-flip-horizontal"></i>
</div> </div>
<div class="bogus_folder_back_placeholder flex alignitemscenter textAlignCenter">
<i class="bogus_folder_icon fa-solid fa-xl fa-right-from-bracket fa-flip-horizontal"></i>
</div>
<div class="flex-container wide100pLess70px character_select_container height100p alignitemscenter"> <div class="flex-container wide100pLess70px character_select_container height100p alignitemscenter">
<div class="wide100p character_name_block"> <div class="wide100p character_name_block">
<span class="ch_name">Go back</span> <span class="ch_name">Go back</span>

View File

@ -22,7 +22,7 @@ export const FILTER_TYPES = {
export const FILTER_STATES = { export const FILTER_STATES = {
SELECTED: { key: 'SELECTED', class: 'selected' }, SELECTED: { key: 'SELECTED', class: 'selected' },
EXCLUDED: { key: 'EXCLUDED', class: 'excluded' }, EXCLUDED: { key: 'EXCLUDED', class: 'excluded' },
UNDEFINED: { key: 'UNDEFINED', class: undefined }, UNDEFINED: { key: 'UNDEFINED', class: 'undefined' },
}; };
/** /**

View File

@ -55,6 +55,7 @@ const ACTIONABLE_TAGS = {
FOLDER: { id: 4, name: 'Always show folders', color: 'rgba(120, 120, 120, 0.5)', action: filterByFolder, icon: 'fa-solid fa-folder-plus', class: 'filterByFolder' }, FOLDER: { id: 4, name: 'Always show folders', color: 'rgba(120, 120, 120, 0.5)', action: filterByFolder, icon: 'fa-solid fa-folder-plus', class: 'filterByFolder' },
VIEW: { id: 2, name: 'Manage tags', color: 'rgba(150, 100, 100, 0.5)', action: onViewTagsListClick, icon: 'fa-solid fa-gear', class: 'manageTags' }, VIEW: { id: 2, name: 'Manage tags', color: 'rgba(150, 100, 100, 0.5)', action: onViewTagsListClick, icon: 'fa-solid fa-gear', class: 'manageTags' },
HINT: { id: 3, name: 'Show Tag List', color: 'rgba(150, 100, 100, 0.5)', action: onTagListHintClick, icon: 'fa-solid fa-tags', class: 'showTagList' }, HINT: { id: 3, name: 'Show Tag List', color: 'rgba(150, 100, 100, 0.5)', action: onTagListHintClick, icon: 'fa-solid fa-tags', class: 'showTagList' },
UNFILTER: { id: 5, name: 'Clear all filters', action: onClearAllFiltersClick, icon: 'fa-solid fa-filter-circle-xmark', class: 'clearAllFilters' },
}; };
const InListActionable = { const InListActionable = {
@ -490,7 +491,7 @@ function appendTagToList(listElement, tag, { removable, selectable, action, isGe
} }
if (tag.excluded && isGeneralList) { if (tag.excluded && isGeneralList) {
toggleTagThreeState(tagElement, FILTER_STATES.EXCLUDED); toggleTagThreeState(tagElement, { stateOverride: FILTER_STATES.EXCLUDED });
} }
if (selectable) { if (selectable) {
@ -536,28 +537,44 @@ function onTagFilterClick(listElement) {
updateTagFilterIndicator(); updateTagFilterIndicator();
} }
function toggleTagThreeState(element, stateOverride = undefined) { function toggleTagThreeState(element, { stateOverride = undefined, simulateClick = false } = {}) {
const states = Object.keys(FILTER_STATES); const states = Object.keys(FILTER_STATES);
const overrideKey = states.includes(stateOverride) ? stateOverride : states.find(key => FILTER_STATES[key] === stateOverride); const overrideKey = states.includes(stateOverride) ? stateOverride : Object.keys(FILTER_STATES).find(key => FILTER_STATES[key] === stateOverride);
const currentState = element.attr('data-toggle-state') ?? states[states.length - 1]; const currentStateIndex = states.indexOf(element.attr('data-toggle-state')) ?? states.length - 1;
const nextState = overrideKey ?? states[(states.indexOf(currentState) + 1) % states.length]; const targetStateIndex = overrideKey !== undefined ? states.indexOf(overrideKey) : (currentStateIndex + 1) % states.length;
element.attr('data-toggle-state', nextState); if (simulateClick) {
// Calculate how many clicks are needed to go from the current state to the target state
let clickCount = 0;
if (targetStateIndex >= currentStateIndex) {
clickCount = targetStateIndex - currentStateIndex;
} else {
clickCount = (states.length - currentStateIndex) + targetStateIndex;
}
console.debug('toggle three-way filter on', element, 'from', currentState, 'to', nextState); for (let i = 0; i < clickCount; i++) {
$(element).trigger('click');
}
console.debug('manually click-toggle three-way filter from', states[currentStateIndex], 'to', states[targetStateIndex], 'on', element);
} else {
element.attr('data-toggle-state', states[targetStateIndex]);
// Update css class and remove all others // Update css class and remove all others
Object.keys(FILTER_STATES).forEach(x => { states.forEach(state => {
if (!isFilterState(x, FILTER_STATES.UNDEFINED)) { element.toggleClass(FILTER_STATES[state].class, state === states[targetStateIndex]);
element.toggleClass(FILTER_STATES[x].class, x === nextState);
}
}); });
return nextState; console.debug('toggle three-way filter from', states[currentStateIndex], 'to', states[targetStateIndex], 'on', element);
}
return states[targetStateIndex];
} }
function runTagFilters(listElement) { function runTagFilters(listElement) {
const tagIds = [...($(listElement).find('.tag.selected:not(.actionable)').map((_, el) => $(el).attr('id')))]; 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')))]; const excludedTagIds = [...($(listElement).find('.tag.excluded:not(.actionable)').map((_, el) => $(el).attr('id')))];
@ -576,10 +593,12 @@ function printTagFilters(type = tag_filter_types.character) {
.sort(compareTagsForSort); .sort(compareTagsForSort);
for (const tag of Object.values(ACTIONABLE_TAGS)) { for (const tag of Object.values(ACTIONABLE_TAGS)) {
appendTagToList(FILTER_SELECTOR, tag, { removable: false, selectable: false, action: tag.action, isGeneralList: true }); if (!power_user.bogus_folders && tag.id == ACTIONABLE_TAGS.FOLDER.id) {
continue;
} }
$(FILTER_SELECTOR).find('.actionable').last().addClass('margin-right-10px'); appendTagToList(FILTER_SELECTOR, tag, { removable: false, selectable: false, action: tag.action, isGeneralList: true });
}
for (const tag of Object.values(InListActionable)) { for (const tag of Object.values(InListActionable)) {
appendTagToList(FILTER_SELECTOR, tag, { removable: false, selectable: false, action: tag.action, isGeneralList: true }); appendTagToList(FILTER_SELECTOR, tag, { removable: false, selectable: false, action: tag.action, isGeneralList: true });
@ -1064,6 +1083,23 @@ function onTagListHintClick() {
console.debug('show_tag_filters', power_user.show_tag_filters); console.debug('show_tag_filters', power_user.show_tag_filters);
} }
function onClearAllFiltersClick() {
console.debug('clear all filters clicked');
// We have to manually go through the elements and unfilter by clicking...
// Thankfully nearly all filter controls are three-state-toggles
const filterTags = $('.rm_tag_controls .rm_tag_filter').find('.tag');
for(const tag of filterTags) {
const toggleState = $(tag).attr('data-toggle-state');
if (toggleState !== undefined && !isFilterState(toggleState ?? FILTER_STATES.UNDEFINED, FILTER_STATES.UNDEFINED)) {
toggleTagThreeState($(tag), { stateOverride: FILTER_STATES.UNDEFINED, simulateClick: true });
}
}
// Reset search too
$('#character_search_bar').val('').trigger('input');
}
jQuery(() => { jQuery(() => {
createTagInput('#tagInput', '#tagList'); createTagInput('#tagInput', '#tagList');
createTagInput('#groupTagInput', '#groupTagList'); createTagInput('#groupTagInput', '#groupTagList');