1 import Sortable from 'sortablejs';
2 import {Component} from './component';
5 * @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
9 const list = item.parentNode;
10 const index = Array.from(list.children).indexOf(item);
11 const newIndex = Math.max(index - 1, 0);
12 list.insertBefore(item, list.children[newIndex] || null);
15 const list = item.parentNode;
16 const index = Array.from(list.children).indexOf(item);
17 const newIndex = Math.min(index + 2, list.children.length);
18 list.insertBefore(item, list.children[newIndex] || null);
20 remove(item, shelfBooksList, allBooksList) {
21 allBooksList.appendChild(item);
23 add(item, shelfBooksList) {
24 shelfBooksList.appendChild(item);
28 export class ShelfSort extends Component {
32 this.input = this.$refs.input;
33 this.shelfBookList = this.$refs.shelfBookList;
34 this.allBookList = this.$refs.allBookList;
35 this.bookSearchInput = this.$refs.bookSearch;
36 this.sortButtonContainer = this.$refs.sortButtonContainer;
41 this.setupListeners();
45 const scrollBoxes = this.elem.querySelectorAll('.scroll-box');
46 for (const scrollBox of scrollBoxes) {
47 new Sortable(scrollBox, {
49 ghostClass: 'primary-background-light',
52 onSort: this.onChange.bind(this),
58 this.elem.addEventListener('click', event => {
59 const sortItemAction = event.target.closest('.scroll-box-item button[data-action]');
61 this.sortItemActionClick(sortItemAction);
65 this.bookSearchInput.addEventListener('input', () => {
66 this.filterBooksByName(this.bookSearchInput.value);
69 this.sortButtonContainer.addEventListener('click', event => {
70 const button = event.target.closest('button[data-sort]');
72 this.sortShelfBooks(button.dataset.sort);
78 * @param {String} filterVal
80 filterBooksByName(filterVal) {
81 // Set height on first search, if not already set, to prevent the distraction
82 // of the list height jumping around
83 if (!this.allBookList.style.height) {
84 this.allBookList.style.height = `${this.allBookList.getBoundingClientRect().height}px`;
87 const books = this.allBookList.children;
88 const lowerFilter = filterVal.trim().toLowerCase();
90 for (const bookEl of books) {
91 const show = !filterVal || bookEl.textContent.toLowerCase().includes(lowerFilter);
92 bookEl.style.display = show ? null : 'none';
97 * Called when a sort item action button is clicked.
98 * @param {HTMLElement} sortItemAction
100 sortItemActionClick(sortItemAction) {
101 const sortItem = sortItemAction.closest('.scroll-box-item');
102 const {action} = sortItemAction.dataset;
104 const actionFunction = itemActions[action];
105 actionFunction(sortItem, this.shelfBookList, this.allBookList);
111 const shelfBookElems = Array.from(this.shelfBookList.querySelectorAll('[data-id]'));
112 this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
115 sortShelfBooks(sortProperty) {
116 const books = Array.from(this.shelfBookList.children);
117 const reverse = sortProperty === this.lastSort;
119 books.sort((bookA, bookB) => {
120 const aProp = bookA.dataset[sortProperty].toLowerCase();
121 const bProp = bookB.dataset[sortProperty].toLowerCase();
124 return bProp.localeCompare(aProp);
127 return aProp.localeCompare(bProp);
130 for (const book of books) {
131 this.shelfBookList.append(book);
134 this.lastSort = (this.lastSort === sortProperty) ? null : sortProperty;