mirror of
				https://github.com/BookStackApp/BookStack.git
				synced 2025-11-03 02:13:16 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import Sortable from 'sortablejs';
 | 
						|
import {Component} from './component';
 | 
						|
 | 
						|
/**
 | 
						|
 * @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
 | 
						|
 */
 | 
						|
const itemActions = {
 | 
						|
    move_up(item) {
 | 
						|
        const list = item.parentNode;
 | 
						|
        const index = Array.from(list.children).indexOf(item);
 | 
						|
        const newIndex = Math.max(index - 1, 0);
 | 
						|
        list.insertBefore(item, list.children[newIndex] || null);
 | 
						|
    },
 | 
						|
    move_down(item) {
 | 
						|
        const list = item.parentNode;
 | 
						|
        const index = Array.from(list.children).indexOf(item);
 | 
						|
        const newIndex = Math.min(index + 2, list.children.length);
 | 
						|
        list.insertBefore(item, list.children[newIndex] || null);
 | 
						|
    },
 | 
						|
    remove(item, shelfBooksList, allBooksList) {
 | 
						|
        allBooksList.appendChild(item);
 | 
						|
    },
 | 
						|
    add(item, shelfBooksList) {
 | 
						|
        shelfBooksList.appendChild(item);
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
export class ShelfSort extends Component {
 | 
						|
 | 
						|
    setup() {
 | 
						|
        this.elem = this.$el;
 | 
						|
        this.input = this.$refs.input;
 | 
						|
        this.shelfBookList = this.$refs.shelfBookList;
 | 
						|
        this.allBookList = this.$refs.allBookList;
 | 
						|
        this.bookSearchInput = this.$refs.bookSearch;
 | 
						|
        this.sortButtonContainer = this.$refs.sortButtonContainer;
 | 
						|
 | 
						|
        this.lastSort = null;
 | 
						|
 | 
						|
        this.initSortable();
 | 
						|
        this.setupListeners();
 | 
						|
    }
 | 
						|
 | 
						|
    initSortable() {
 | 
						|
        const scrollBoxes = this.elem.querySelectorAll('.scroll-box');
 | 
						|
        for (const scrollBox of scrollBoxes) {
 | 
						|
            new Sortable(scrollBox, {
 | 
						|
                group: 'shelf-books',
 | 
						|
                ghostClass: 'primary-background-light',
 | 
						|
                handle: '.handle',
 | 
						|
                animation: 150,
 | 
						|
                onSort: this.onChange.bind(this),
 | 
						|
            });
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    setupListeners() {
 | 
						|
        this.elem.addEventListener('click', event => {
 | 
						|
            const sortItemAction = event.target.closest('.scroll-box-item button[data-action]');
 | 
						|
            if (sortItemAction) {
 | 
						|
                this.sortItemActionClick(sortItemAction);
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        this.bookSearchInput.addEventListener('input', () => {
 | 
						|
            this.filterBooksByName(this.bookSearchInput.value);
 | 
						|
        });
 | 
						|
 | 
						|
        this.sortButtonContainer.addEventListener('click', event => {
 | 
						|
            const button = event.target.closest('button[data-sort]');
 | 
						|
            if (button) {
 | 
						|
                this.sortShelfBooks(button.dataset.sort);
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param {String} filterVal
 | 
						|
     */
 | 
						|
    filterBooksByName(filterVal) {
 | 
						|
        // Set height on first search, if not already set, to prevent the distraction
 | 
						|
        // of the list height jumping around
 | 
						|
        if (!this.allBookList.style.height) {
 | 
						|
            this.allBookList.style.height = `${this.allBookList.getBoundingClientRect().height}px`;
 | 
						|
        }
 | 
						|
 | 
						|
        const books = this.allBookList.children;
 | 
						|
        const lowerFilter = filterVal.trim().toLowerCase();
 | 
						|
 | 
						|
        for (const bookEl of books) {
 | 
						|
            const show = !filterVal || bookEl.textContent.toLowerCase().includes(lowerFilter);
 | 
						|
            bookEl.style.display = show ? null : 'none';
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Called when a sort item action button is clicked.
 | 
						|
     * @param {HTMLElement} sortItemAction
 | 
						|
     */
 | 
						|
    sortItemActionClick(sortItemAction) {
 | 
						|
        const sortItem = sortItemAction.closest('.scroll-box-item');
 | 
						|
        const {action} = sortItemAction.dataset;
 | 
						|
 | 
						|
        const actionFunction = itemActions[action];
 | 
						|
        actionFunction(sortItem, this.shelfBookList, this.allBookList);
 | 
						|
 | 
						|
        this.onChange();
 | 
						|
    }
 | 
						|
 | 
						|
    onChange() {
 | 
						|
        const shelfBookElems = Array.from(this.shelfBookList.querySelectorAll('[data-id]'));
 | 
						|
        this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
 | 
						|
    }
 | 
						|
 | 
						|
    sortShelfBooks(sortProperty) {
 | 
						|
        const books = Array.from(this.shelfBookList.children);
 | 
						|
        const reverse = sortProperty === this.lastSort;
 | 
						|
 | 
						|
        books.sort((bookA, bookB) => {
 | 
						|
            const aProp = bookA.dataset[sortProperty].toLowerCase();
 | 
						|
            const bProp = bookB.dataset[sortProperty].toLowerCase();
 | 
						|
 | 
						|
            if (reverse) {
 | 
						|
                return bProp.localeCompare(aProp);
 | 
						|
            }
 | 
						|
 | 
						|
            return aProp.localeCompare(bProp);
 | 
						|
        });
 | 
						|
 | 
						|
        for (const book of books) {
 | 
						|
            this.shelfBookList.append(book);
 | 
						|
        }
 | 
						|
 | 
						|
        this.lastSort = (this.lastSort === sortProperty) ? null : sortProperty;
 | 
						|
        this.onChange();
 | 
						|
    }
 | 
						|
 | 
						|
}
 |