1 import Sortable from "sortablejs";
2 import {Component} from "./component";
5 * @type {Object<string, function(HTMLElement, HTMLElement, HTMLElement)>}
8 move_up(item, shelfBooksList, allBooksList) {
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);
14 move_down(item, shelfBooksList, allBooksList) {
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, allBooksList) {
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', event => {
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) {
82 // Set height on first search, if not already set, to prevent the distraction
83 // of the list height jumping around
84 if (!this.allBookList.style.height) {
85 this.allBookList.style.height = this.allBookList.getBoundingClientRect().height + 'px';
88 const books = this.allBookList.children;
89 const lowerFilter = filterVal.trim().toLowerCase();
91 for (const bookEl of books) {
92 const show = !filterVal || bookEl.textContent.toLowerCase().includes(lowerFilter);
93 bookEl.style.display = show ? null : 'none';
98 * Called when a sort item action button is clicked.
99 * @param {HTMLElement} sortItemAction
101 sortItemActionClick(sortItemAction) {
102 const sortItem = sortItemAction.closest('.scroll-box-item');
103 const action = sortItemAction.dataset.action;
105 const actionFunction = itemActions[action];
106 actionFunction(sortItem, this.shelfBookList, this.allBookList);
112 const shelfBookElems = Array.from(this.shelfBookList.querySelectorAll('[data-id]'));
113 this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(',');
116 sortShelfBooks(sortProperty) {
117 const books = Array.from(this.shelfBookList.children);
118 const reverse = sortProperty === this.lastSort;
120 books.sort((bookA, bookB) => {
121 const aProp = bookA.dataset[sortProperty].toLowerCase();
122 const bProp = bookB.dataset[sortProperty].toLowerCase();
125 return aProp < bProp ? (aProp === bProp ? 0 : 1) : -1;
128 return aProp < bProp ? (aProp === bProp ? 0 : -1) : 1;
131 for (const book of books) {
132 this.shelfBookList.append(book);
135 this.lastSort = (this.lastSort === sortProperty) ? null : sortProperty;